aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Adler <madler@alumni.caltech.edu>2016-12-04 17:09:33 -0800
committerMark Adler <madler@alumni.caltech.edu>2016-12-04 18:35:41 -0800
commit44dfd831d24f9b627ab666cf0973b0dce98fabba (patch)
tree63d4dbb73dd292e96beb4e171c12a9a36399d6bc
parent3f8c768745e85d0e63ba306581710c6dc9db0d65 (diff)
downloadzlib-44dfd831d24f9b627ab666cf0973b0dce98fabba.tar.gz
zlib-44dfd831d24f9b627ab666cf0973b0dce98fabba.tar.bz2
zlib-44dfd831d24f9b627ab666cf0973b0dce98fabba.zip
Add gzfread(), duplicating the interface of fread().
-rw-r--r--gzread.c136
-rw-r--r--zlib.h30
2 files changed, 126 insertions, 40 deletions
diff --git a/gzread.c b/gzread.c
index b05229e..ebf2c18 100644
--- a/gzread.c
+++ b/gzread.c
@@ -12,6 +12,7 @@ local int gz_look OF((gz_statep));
12local int gz_decomp OF((gz_statep)); 12local int gz_decomp OF((gz_statep));
13local int gz_fetch OF((gz_statep)); 13local int gz_fetch OF((gz_statep));
14local int gz_skip OF((gz_statep, z_off64_t)); 14local int gz_skip OF((gz_statep, z_off64_t));
15local z_size_t gz_read OF((gz_statep, voidp, z_size_t));
15 16
16/* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from 17/* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from
17 state->fd, and update state->eof, state->err, and state->msg as appropriate. 18 state->fd, and update state->eof, state->err, and state->msg as appropriate.
@@ -284,33 +285,17 @@ local int gz_skip(state, len)
284 return 0; 285 return 0;
285} 286}
286 287
287/* -- see zlib.h -- */ 288/* Read len bytes into buf from file, or less than len up to the end of the
288int ZEXPORT gzread(file, buf, len) 289 input. Return the number of bytes read. If zero is returned, either the
289 gzFile file; 290 end of file was reached, or there was an error. state->err must be
291 consulted in that case to determine which. */
292local z_size_t gz_read(state, buf, len)
293 gz_statep state;
290 voidp buf; 294 voidp buf;
291 unsigned len; 295 z_size_t len;
292{ 296{
293 unsigned got, n; 297 z_size_t got;
294 gz_statep state; 298 unsigned n;
295 z_streamp strm;
296
297 /* get internal structure */
298 if (file == NULL)
299 return -1;
300 state = (gz_statep)file;
301 strm = &(state->strm);
302
303 /* check that we're reading and that there's no (serious) error */
304 if (state->mode != GZ_READ ||
305 (state->err != Z_OK && state->err != Z_BUF_ERROR))
306 return -1;
307
308 /* since an int is returned, make sure len fits in one, otherwise return
309 with an error (this avoids the flaw in the interface) */
310 if ((int)len < 0) {
311 gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
312 return -1;
313 }
314 299
315 /* if len is zero, avoid unnecessary operations */ 300 /* if len is zero, avoid unnecessary operations */
316 if (len == 0) 301 if (len == 0)
@@ -320,32 +305,38 @@ int ZEXPORT gzread(file, buf, len)
320 if (state->seek) { 305 if (state->seek) {
321 state->seek = 0; 306 state->seek = 0;
322 if (gz_skip(state, state->skip) == -1) 307 if (gz_skip(state, state->skip) == -1)
323 return -1; 308 return 0;
324 } 309 }
325 310
326 /* get len bytes to buf, or less than len if at the end */ 311 /* get len bytes to buf, or less than len if at the end */
327 got = 0; 312 got = 0;
328 do { 313 do {
314 /* set n to the maximum amount of len that fits in an unsigned int */
315 n = -1;
316 if (n > len)
317 n = len;
318
329 /* first just try copying data from the output buffer */ 319 /* first just try copying data from the output buffer */
330 if (state->x.have) { 320 if (state->x.have) {
331 n = state->x.have > len ? len : state->x.have; 321 if (state->x.have < n)
322 n = state->x.have;
332 memcpy(buf, state->x.next, n); 323 memcpy(buf, state->x.next, n);
333 state->x.next += n; 324 state->x.next += n;
334 state->x.have -= n; 325 state->x.have -= n;
335 } 326 }
336 327
337 /* output buffer empty -- return if we're at the end of the input */ 328 /* output buffer empty -- return if we're at the end of the input */
338 else if (state->eof && strm->avail_in == 0) { 329 else if (state->eof && state->strm.avail_in == 0) {
339 state->past = 1; /* tried to read past end */ 330 state->past = 1; /* tried to read past end */
340 break; 331 break;
341 } 332 }
342 333
343 /* need output data -- for small len or new stream load up our output 334 /* need output data -- for small len or new stream load up our output
344 buffer */ 335 buffer */
345 else if (state->how == LOOK || len < (state->size << 1)) { 336 else if (state->how == LOOK || n < (state->size << 1)) {
346 /* get more output, looking for header if required */ 337 /* get more output, looking for header if required */
347 if (gz_fetch(state) == -1) 338 if (gz_fetch(state) == -1)
348 return -1; 339 return 0;
349 continue; /* no progress yet -- go back to copy above */ 340 continue; /* no progress yet -- go back to copy above */
350 /* the copy above assures that we will leave with space in the 341 /* the copy above assures that we will leave with space in the
351 output buffer, allowing at least one gzungetc() to succeed */ 342 output buffer, allowing at least one gzungetc() to succeed */
@@ -353,16 +344,16 @@ int ZEXPORT gzread(file, buf, len)
353 344
354 /* large len -- read directly into user buffer */ 345 /* large len -- read directly into user buffer */
355 else if (state->how == COPY) { /* read directly */ 346 else if (state->how == COPY) { /* read directly */
356 if (gz_load(state, (unsigned char *)buf, len, &n) == -1) 347 if (gz_load(state, (unsigned char *)buf, n, &n) == -1)
357 return -1; 348 return 0;
358 } 349 }
359 350
360 /* large len -- decompress directly into user buffer */ 351 /* large len -- decompress directly into user buffer */
361 else { /* state->how == GZIP */ 352 else { /* state->how == GZIP */
362 strm->avail_out = len; 353 state->strm.avail_out = n;
363 strm->next_out = (unsigned char *)buf; 354 state->strm.next_out = (unsigned char *)buf;
364 if (gz_decomp(state) == -1) 355 if (gz_decomp(state) == -1)
365 return -1; 356 return 0;
366 n = state->x.have; 357 n = state->x.have;
367 state->x.have = 0; 358 state->x.have = 0;
368 } 359 }
@@ -374,8 +365,75 @@ int ZEXPORT gzread(file, buf, len)
374 state->x.pos += n; 365 state->x.pos += n;
375 } while (len); 366 } while (len);
376 367
377 /* return number of bytes read into user buffer (will fit in int) */ 368 /* return number of bytes read into user buffer */
378 return (int)got; 369 return got;
370}
371
372/* -- see zlib.h -- */
373int ZEXPORT gzread(file, buf, len)
374 gzFile file;
375 voidp buf;
376 unsigned len;
377{
378 gz_statep state;
379
380 /* get internal structure */
381 if (file == NULL)
382 return -1;
383 state = (gz_statep)file;
384
385 /* check that we're reading and that there's no (serious) error */
386 if (state->mode != GZ_READ ||
387 (state->err != Z_OK && state->err != Z_BUF_ERROR))
388 return -1;
389
390 /* since an int is returned, make sure len fits in one, otherwise return
391 with an error (this avoids a flaw in the interface) */
392 if ((int)len < 0) {
393 gz_error(state, Z_STREAM_ERROR, "request does not fit in an int");
394 return -1;
395 }
396
397 /* read len or fewer bytes to buf */
398 len = gz_read(state, buf, len);
399
400 /* check for an error */
401 if (len == 0 && state->err != Z_OK && state->err != Z_BUF_ERROR)
402 return -1;
403
404 /* return the number of bytes read (this is assured to fit in an int) */
405 return (int)len;
406}
407
408/* -- see zlib.h -- */
409z_size_t ZEXPORT gzfread(buf, size, nitems, file)
410 voidp buf;
411 z_size_t size;
412 z_size_t nitems;
413 gzFile file;
414{
415 z_size_t len;
416 gz_statep state;
417
418 /* get internal structure */
419 if (file == NULL)
420 return 0;
421 state = (gz_statep)file;
422
423 /* check that we're reading and that there's no (serious) error */
424 if (state->mode != GZ_READ ||
425 (state->err != Z_OK && state->err != Z_BUF_ERROR))
426 return 0;
427
428 /* compute bytes to read -- error on overflow */
429 len = nitems * size;
430 if (size && len / size != nitems) {
431 gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t");
432 return 0;
433 }
434
435 /* read len or fewer bytes to buf, return the number of full items read */
436 return len ? gz_read(state, buf, len) / size : 0;
379} 437}
380 438
381/* -- see zlib.h -- */ 439/* -- see zlib.h -- */
@@ -408,8 +466,8 @@ int ZEXPORT gzgetc(file)
408 return *(state->x.next)++; 466 return *(state->x.next)++;
409 } 467 }
410 468
411 /* nothing there -- try gzread() */ 469 /* nothing there -- try gz_read() */
412 ret = gzread(file, buf, 1); 470 ret = gz_read(state, buf, 1);
413 return ret < 1 ? -1 : buf[0]; 471 return ret < 1 ? -1 : buf[0];
414} 472}
415 473
diff --git a/zlib.h b/zlib.h
index b396709..ff4469d 100644
--- a/zlib.h
+++ b/zlib.h
@@ -1388,7 +1388,35 @@ ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len));
1388 case. 1388 case.
1389 1389
1390 gzread returns the number of uncompressed bytes actually read, less than 1390 gzread returns the number of uncompressed bytes actually read, less than
1391 len for end of file, or -1 for error. 1391 len for end of file, or -1 for error. If len is too large to fit in an int,
1392 then nothing is read, -1 is returned, and the error state is set to
1393 Z_STREAM_ERROR.
1394*/
1395
1396ZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems,
1397 gzFile file));
1398/*
1399 Read up to nitems items of size size from file to buf, otherwise operating
1400 as gzread() does. This duplicates the interface of stdio's fread(), with
1401 size_t request and return types. If the library defines size_t, then
1402 z_size_t is identical to size_t. If not, then z_size_t is an unsigned
1403 integer type that can contain a pointer.
1404
1405 gzfread() returns the number of full items read of size size, or zero if
1406 the end of the file was reached and a full item could not be read, or if
1407 there was an error. gzerror() must be consulted if zero is returned in
1408 order to determine if there was an error. If the multiplication of size and
1409 nitems overflows, i.e. the product does not fit in a z_size_t, then nothing
1410 is read, zero is returned, and the error state is set to Z_STREAM_ERROR.
1411
1412 In the event that the end of file is reached and only a partial item is
1413 available at the end, i.e. the remaining uncompressed data length is not a
1414 multiple of size, then the final partial item is nevetheless read into buf
1415 and the end-of-file flag is set. The length of the partial item read is not
1416 provided, but could be inferred from the result of gztell(). This behavior
1417 is the same as the behavior of fread() implementations in common libraries,
1418 but it prevents the direct use of gzfread() to read a concurrently written
1419 file, reseting and retrying on end-of-file, when size is not 1.
1392*/ 1420*/
1393 1421
1394ZEXTERN int ZEXPORT gzwrite OF((gzFile file, 1422ZEXTERN int ZEXPORT gzwrite OF((gzFile file,