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 |
