| /* |
| $NiH: zip_fread.c,v 1.20 2006/02/22 19:52:20 dillo Exp $ |
| |
| zip_fread.c -- read from file |
| Copyright (C) 1999, 2004, 2005 Dieter Baron and Thomas Klausner |
| |
| This file is part of libzip, a library to manipulate ZIP archives. |
| The authors can be contacted at <nih@giga.or.at> |
| |
| Redistribution and use in source and binary forms, with or without |
| modification, are permitted provided that the following conditions |
| are met: |
| 1. Redistributions of source code must retain the above copyright |
| notice, this list of conditions and the following disclaimer. |
| 2. Redistributions in binary form must reproduce the above copyright |
| notice, this list of conditions and the following disclaimer in |
| the documentation and/or other materials provided with the |
| distribution. |
| 3. The names of the authors may not be used to endorse or promote |
| products derived from this software without specific prior |
| written permission. |
| |
| THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS |
| OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY |
| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE |
| GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER |
| IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
| OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN |
| IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| |
| |
| #include "zip.h" |
| #include "zipint.h" |
| |
| |
| |
| ssize_t |
| zip_fread(struct zip_file *zf, void *outbuf, size_t toread) |
| { |
| int ret; |
| size_t out_before, len; |
| int i; |
| |
| if (!zf) |
| return -1; |
| |
| if (zf->error.zip_err != 0) |
| return -1; |
| |
| if ((zf->flags & ZIP_ZF_EOF) || (toread == 0)) |
| return 0; |
| |
| if (zf->bytes_left == 0) { |
| zf->flags |= ZIP_ZF_EOF; |
| if (zf->flags & ZIP_ZF_CRC) { |
| if (zf->crc != zf->crc_orig) { |
| _zip_error_set(&zf->error, ZIP_ER_CRC, 0); |
| return -1; |
| } |
| } |
| return 0; |
| } |
| |
| if ((zf->flags & ZIP_ZF_DECOMP) == 0) { |
| ret = _zip_file_fillbuf(outbuf, toread, zf); |
| if (ret > 0) { |
| if (zf->flags & ZIP_ZF_CRC) |
| zf->crc = crc32(zf->crc, (Bytef *)outbuf, ret); |
| zf->bytes_left -= ret; |
| } |
| return ret; |
| } |
| |
| zf->zstr->next_out = (Bytef *)outbuf; |
| zf->zstr->avail_out = toread; |
| out_before = zf->zstr->total_out; |
| |
| /* endless loop until something has been accomplished */ |
| for (;;) { |
| ret = inflate(zf->zstr, Z_SYNC_FLUSH); |
| |
| switch (ret) { |
| case Z_OK: |
| case Z_STREAM_END: |
| /* all ok */ |
| /* Z_STREAM_END probably won't happen, since we didn't |
| have a header */ |
| len = zf->zstr->total_out - out_before; |
| if (len >= zf->bytes_left || len >= toread) { |
| if (zf->flags & ZIP_ZF_CRC) |
| zf->crc = crc32(zf->crc, (Bytef *)outbuf, len); |
| zf->bytes_left -= len; |
| return len; |
| } |
| break; |
| |
| case Z_BUF_ERROR: |
| if (zf->zstr->avail_in == 0) { |
| i = _zip_file_fillbuf(zf->buffer, BUFSIZE, zf); |
| if (i == 0) { |
| _zip_error_set(&zf->error, ZIP_ER_INCONS, 0); |
| return -1; |
| } |
| else if (i < 0) |
| return -1; |
| zf->zstr->next_in = (Bytef *)zf->buffer; |
| zf->zstr->avail_in = i; |
| continue; |
| } |
| /* fallthrough */ |
| case Z_NEED_DICT: |
| case Z_DATA_ERROR: |
| case Z_STREAM_ERROR: |
| case Z_MEM_ERROR: |
| _zip_error_set(&zf->error, ZIP_ER_ZLIB, ret); |
| return -1; |
| } |
| } |
| } |