diff options
author | Mark Adler <madler@alumni.caltech.edu> | 2016-12-04 18:29:43 -0800 |
---|---|---|
committer | Mark Adler <madler@alumni.caltech.edu> | 2016-12-04 18:47:34 -0800 |
commit | 77bc4f8944c0e1a1fd4689eddbcead6e93bef58a (patch) | |
tree | 4de4ee562e63d8ec74878d58041b53a291ffc443 | |
parent | 44dfd831d24f9b627ab666cf0973b0dce98fabba (diff) | |
download | zlib-77bc4f8944c0e1a1fd4689eddbcead6e93bef58a.tar.gz zlib-77bc4f8944c0e1a1fd4689eddbcead6e93bef58a.tar.bz2 zlib-77bc4f8944c0e1a1fd4689eddbcead6e93bef58a.zip |
Add gzfwrite(), duplicating the interface of fwrite().
-rw-r--r-- | gzwrite.c | 138 | ||||
-rw-r--r-- | zlib.h | 14 |
2 files changed, 112 insertions, 40 deletions
@@ -9,6 +9,7 @@ | |||
9 | local int gz_init OF((gz_statep)); | 9 | local int gz_init OF((gz_statep)); |
10 | local int gz_comp OF((gz_statep, int)); | 10 | local int gz_comp OF((gz_statep, int)); |
11 | local int gz_zero OF((gz_statep, z_off64_t)); | 11 | local int gz_zero OF((gz_statep, z_off64_t)); |
12 | local z_size_t gz_write OF((gz_statep, voidpc, z_size_t)); | ||
12 | 13 | ||
13 | /* Initialize state for writing a gzip file. Mark initialization by setting | 14 | /* Initialize state for writing a gzip file. Mark initialization by setting |
14 | state->size to non-zero. Return -1 on a memory allocation failure, or 0 on | 15 | state->size to non-zero. Return -1 on a memory allocation failure, or 0 on |
@@ -170,32 +171,14 @@ local int gz_zero(state, len) | |||
170 | return 0; | 171 | return 0; |
171 | } | 172 | } |
172 | 173 | ||
173 | /* -- see zlib.h -- */ | 174 | /* Write len bytes from buf to file. Return the number of bytes written. If |
174 | int ZEXPORT gzwrite(file, buf, len) | 175 | the returned value is less than len, then there was an error. */ |
175 | gzFile file; | 176 | local z_size_t gz_write(state, buf, len) |
177 | gz_statep state; | ||
176 | voidpc buf; | 178 | voidpc buf; |
177 | unsigned len; | 179 | z_size_t len; |
178 | { | 180 | { |
179 | unsigned put = len; | 181 | z_size_t put = len; |
180 | gz_statep state; | ||
181 | z_streamp strm; | ||
182 | |||
183 | /* get internal structure */ | ||
184 | if (file == NULL) | ||
185 | return 0; | ||
186 | state = (gz_statep)file; | ||
187 | strm = &(state->strm); | ||
188 | |||
189 | /* check that we're writing and that there's no error */ | ||
190 | if (state->mode != GZ_WRITE || state->err != Z_OK) | ||
191 | return 0; | ||
192 | |||
193 | /* since an int is returned, make sure len fits in one, otherwise return | ||
194 | with an error (this avoids the flaw in the interface) */ | ||
195 | if ((int)len < 0) { | ||
196 | gz_error(state, Z_DATA_ERROR, "requested length does not fit in int"); | ||
197 | return 0; | ||
198 | } | ||
199 | 182 | ||
200 | /* if len is zero, avoid unnecessary operations */ | 183 | /* if len is zero, avoid unnecessary operations */ |
201 | if (len == 0) | 184 | if (len == 0) |
@@ -218,14 +201,15 @@ int ZEXPORT gzwrite(file, buf, len) | |||
218 | do { | 201 | do { |
219 | unsigned have, copy; | 202 | unsigned have, copy; |
220 | 203 | ||
221 | if (strm->avail_in == 0) | 204 | if (state->strm.avail_in == 0) |
222 | strm->next_in = state->in; | 205 | state->strm.next_in = state->in; |
223 | have = (unsigned)((strm->next_in + strm->avail_in) - state->in); | 206 | have = (unsigned)((state->strm.next_in + state->strm.avail_in) - |
207 | state->in); | ||
224 | copy = state->size - have; | 208 | copy = state->size - have; |
225 | if (copy > len) | 209 | if (copy > len) |
226 | copy = len; | 210 | copy = len; |
227 | memcpy(state->in + have, buf, copy); | 211 | memcpy(state->in + have, buf, copy); |
228 | strm->avail_in += copy; | 212 | state->strm.avail_in += copy; |
229 | state->x.pos += copy; | 213 | state->x.pos += copy; |
230 | buf = (const char *)buf + copy; | 214 | buf = (const char *)buf + copy; |
231 | len -= copy; | 215 | len -= copy; |
@@ -235,19 +219,83 @@ int ZEXPORT gzwrite(file, buf, len) | |||
235 | } | 219 | } |
236 | else { | 220 | else { |
237 | /* consume whatever's left in the input buffer */ | 221 | /* consume whatever's left in the input buffer */ |
238 | if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) | 222 | if (state->strm.avail_in && gz_comp(state, Z_NO_FLUSH) == -1) |
239 | return 0; | 223 | return 0; |
240 | 224 | ||
241 | /* directly compress user buffer to file */ | 225 | /* directly compress user buffer to file */ |
242 | strm->avail_in = len; | 226 | state->strm.next_in = (z_const Bytef *)buf; |
243 | strm->next_in = (z_const Bytef *)buf; | 227 | do { |
244 | state->x.pos += len; | 228 | unsigned n = -1; |
245 | if (gz_comp(state, Z_NO_FLUSH) == -1) | 229 | if (n > len) |
246 | return 0; | 230 | n = len; |
231 | state->strm.avail_in = n; | ||
232 | state->x.pos += n; | ||
233 | if (gz_comp(state, Z_NO_FLUSH) == -1) | ||
234 | return 0; | ||
235 | len -= n; | ||
236 | } while (len); | ||
237 | } | ||
238 | |||
239 | /* input was all buffered or compressed */ | ||
240 | return put; | ||
241 | } | ||
242 | |||
243 | /* -- see zlib.h -- */ | ||
244 | int ZEXPORT gzwrite(file, buf, len) | ||
245 | gzFile file; | ||
246 | voidpc buf; | ||
247 | unsigned len; | ||
248 | { | ||
249 | gz_statep state; | ||
250 | |||
251 | /* get internal structure */ | ||
252 | if (file == NULL) | ||
253 | return 0; | ||
254 | state = (gz_statep)file; | ||
255 | |||
256 | /* check that we're writing and that there's no error */ | ||
257 | if (state->mode != GZ_WRITE || state->err != Z_OK) | ||
258 | return 0; | ||
259 | |||
260 | /* since an int is returned, make sure len fits in one, otherwise return | ||
261 | with an error (this avoids a flaw in the interface) */ | ||
262 | if ((int)len < 0) { | ||
263 | gz_error(state, Z_DATA_ERROR, "requested length does not fit in int"); | ||
264 | return 0; | ||
265 | } | ||
266 | |||
267 | /* write len bytes from buf (the return value will fit in an int) */ | ||
268 | return (int)gz_write(state, buf, len); | ||
269 | } | ||
270 | |||
271 | /* -- see zlib.h -- */ | ||
272 | z_size_t ZEXPORT gzfwrite(buf, size, nitems, file) | ||
273 | voidpc buf; | ||
274 | z_size_t size; | ||
275 | z_size_t nitems; | ||
276 | gzFile file; | ||
277 | { | ||
278 | z_size_t len; | ||
279 | gz_statep state; | ||
280 | |||
281 | /* get internal structure */ | ||
282 | if (file == NULL) | ||
283 | return 0; | ||
284 | state = (gz_statep)file; | ||
285 | |||
286 | /* check that we're writing and that there's no error */ | ||
287 | if (state->mode != GZ_WRITE || state->err != Z_OK) | ||
288 | return 0; | ||
289 | |||
290 | /* compute bytes to read -- error on overflow */ | ||
291 | len = nitems * size; | ||
292 | if (size && len / size != nitems) { | ||
293 | gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t"); | ||
294 | return 0; | ||
247 | } | 295 | } |
248 | 296 | ||
249 | /* input was all buffered or compressed (put will fit in int) */ | 297 | /* write len bytes to buf, return the number of full items written */ |
250 | return (int)put; | 298 | return len ? gz_write(state, buf, len) / size : 0; |
251 | } | 299 | } |
252 | 300 | ||
253 | /* -- see zlib.h -- */ | 301 | /* -- see zlib.h -- */ |
@@ -293,7 +341,7 @@ int ZEXPORT gzputc(file, c) | |||
293 | 341 | ||
294 | /* no room in buffer or not initialized, use gz_write() */ | 342 | /* no room in buffer or not initialized, use gz_write() */ |
295 | buf[0] = (unsigned char)c; | 343 | buf[0] = (unsigned char)c; |
296 | if (gzwrite(file, buf, 1) != 1) | 344 | if (gz_write(state, buf, 1) != 1) |
297 | return -1; | 345 | return -1; |
298 | return c & 0xff; | 346 | return c & 0xff; |
299 | } | 347 | } |
@@ -304,11 +352,21 @@ int ZEXPORT gzputs(file, str) | |||
304 | const char *str; | 352 | const char *str; |
305 | { | 353 | { |
306 | int ret; | 354 | int ret; |
307 | unsigned len; | 355 | z_size_t len; |
356 | gz_statep state; | ||
357 | |||
358 | /* get internal structure */ | ||
359 | if (file == NULL) | ||
360 | return -1; | ||
361 | state = (gz_statep)file; | ||
362 | |||
363 | /* check that we're writing and that there's no error */ | ||
364 | if (state->mode != GZ_WRITE || state->err != Z_OK) | ||
365 | return -1; | ||
308 | 366 | ||
309 | /* write string */ | 367 | /* write string */ |
310 | len = (unsigned)strlen(str); | 368 | len = strlen(str); |
311 | ret = gzwrite(file, str, len); | 369 | ret = gz_write(state, str, len); |
312 | return ret == 0 && len != 0 ? -1 : ret; | 370 | return ret == 0 && len != 0 ? -1 : ret; |
313 | } | 371 | } |
314 | 372 | ||
@@ -1427,6 +1427,20 @@ ZEXTERN int ZEXPORT gzwrite OF((gzFile file, | |||
1427 | error. | 1427 | error. |
1428 | */ | 1428 | */ |
1429 | 1429 | ||
1430 | ZEXTERN z_size_t ZEXPORT gzfwrite OF((voidpc buf, z_size_t size, | ||
1431 | z_size_t nitems, gzFile file)); | ||
1432 | /* | ||
1433 | gzfwrite() writes nitems items of size size from buf to file, duplicating | ||
1434 | the interface of stdio's fwrite(), with size_t request and return types. If | ||
1435 | the library defines size_t, then z_size_t is identical to size_t. If not, | ||
1436 | then z_size_t is an unsigned integer type that can contain a pointer. | ||
1437 | |||
1438 | gzfwrite() returns the number of full items written of size size, or zero | ||
1439 | if there was an error. If the multiplication of size and nitems overflows, | ||
1440 | i.e. the product does not fit in a z_size_t, then nothing is written, zero | ||
1441 | is returned, and the error state is set to Z_STREAM_ERROR. | ||
1442 | */ | ||
1443 | |||
1430 | ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...)); | 1444 | ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...)); |
1431 | /* | 1445 | /* |
1432 | Converts, formats, and writes the arguments to the compressed file under | 1446 | Converts, formats, and writes the arguments to the compressed file under |