static void /* gz_decomp */ zlib_read(FILE_F state, unsigned char *buf, unsigned int count) { int ret = 0; /* XXX */ guint32 crc, len; z_streamp strm = &(state->strm); unsigned char *buf2 = buf; unsigned int count2 = count; strm->avail_out = count; strm->next_out = buf; /* fill output buffer up to end of deflate stream or error */ do { /* get more input for inflate() */ if (state->avail_in == 0 && fill_in_buffer(state) == -1) break; if (state->avail_in == 0) { /* EOF */ state->err = FTAP_ERR_SHORT_READ; state->err_info = NULL; break; } strm->avail_in = state->avail_in; strm->next_in = state->next_in; /* decompress and handle errors */ #ifdef Z_BLOCK ret = inflate(strm, Z_BLOCK); #else ret = inflate(strm, Z_NO_FLUSH); #endif state->avail_in = strm->avail_in; state->next_in = strm->next_in; if (ret == Z_STREAM_ERROR) { state->err = FTAP_ERR_DECOMPRESS; state->err_info = strm->msg; break; } if (ret == Z_NEED_DICT) { state->err = FTAP_ERR_DECOMPRESS; state->err_info = "preset dictionary needed"; break; } if (ret == Z_MEM_ERROR) { /* This means "not enough memory". */ state->err = ENOMEM; state->err_info = NULL; break; } if (ret == Z_DATA_ERROR) { /* deflate stream invalid */ state->err = FTAP_ERR_DECOMPRESS; state->err_info = strm->msg; break; } /* * XXX - Z_BUF_ERROR? */ strm->adler = crc32(strm->adler, buf2, count2 - strm->avail_out); #ifdef Z_BLOCK if (state->fast_seek_cur) { struct zlib_cur_seek_point *cur = (struct zlib_cur_seek_point *) state->fast_seek_cur; unsigned int ready = count2 - strm->avail_out; if (ready < ZLIB_WINSIZE) { guint left = ZLIB_WINSIZE - cur->pos; if (ready >= left) { memcpy(cur->window + cur->pos, buf2, left); if (ready != left) memcpy(cur->window, buf2 + left, ready - left); cur->pos = ready - left; cur->have += ready; } else { memcpy(cur->window + cur->pos, buf2, ready); cur->pos += ready; cur->have += ready; } if (cur->have >= ZLIB_WINSIZE) cur->have = ZLIB_WINSIZE; } else { memcpy(cur->window, buf2 + (ready - ZLIB_WINSIZE), ZLIB_WINSIZE); cur->pos = 0; cur->have = ZLIB_WINSIZE; } if (cur->have >= ZLIB_WINSIZE && ret != Z_STREAM_END && (strm->data_type & 128) && !(strm->data_type & 64)) zlib_fast_seek_add(state, cur, (strm->data_type & 7), state->raw_pos - strm->avail_in, state->pos + (count - strm->avail_out)); } #endif buf2 = (buf2 + count2 - strm->avail_out); count2 = strm->avail_out; } while (strm->avail_out && ret != Z_STREAM_END); /* update available output and crc check value */ state->next = buf; state->have = count - strm->avail_out; /* Check gzip trailer if at end of deflate stream. We don't fail immediately here, we just set an error indication, so that we try to process what data we got before the error. The next attempt to read something past that data will get the error. */ if (ret == Z_STREAM_END) { if (gz_next4(state, &crc) != -1 && gz_next4(state, &len) != -1) { if (crc != strm->adler && !state->dont_check_crc) { state->err = FTAP_ERR_DECOMPRESS; state->err_info = "bad CRC"; } else if (len != (strm->total_out & 0xffffffffL)) { state->err = FTAP_ERR_DECOMPRESS; state->err_info = "length field wrong"; } } state->compression = UNKNOWN; /* ready for next stream, once have is 0 */ g_free(state->fast_seek_cur); state->fast_seek_cur = NULL; } }
/* Decompress from input to the provided next_out and avail_out in the state. If the end of the compressed data is reached, then verify the gzip trailer check value and length (modulo 2^32). state->have and state->next are set to point to the just decompressed data, and the crc is updated. If the trailer is verified, state->how is reset to LOOK to look for the next gzip stream or raw data, once state->have is depleted. Returns 0 on success, -1 on failure. Failures may include invalid compressed data or a failed gzip trailer verification. */ local int gz_decomp(gz_statep state) { int ret; unsigned had; unsigned long crc, len; z_streamp strm = &(state->strm); /* fill output buffer up to end of deflate stream */ had = strm->avail_out; do { /* get more input for inflate() */ if (strm->avail_in == 0 && gz_avail(state) == -1) return -1; if (strm->avail_in == 0) { gz_error(state, Z_DATA_ERROR, "unexpected end of file"); return -1; } /* decompress and handle errors */ ret = inflate(strm, Z_NO_FLUSH); if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) { gz_error(state, Z_STREAM_ERROR, "internal error: inflate stream corrupt"); return -1; } if (ret == Z_MEM_ERROR) { gz_error(state, Z_MEM_ERROR, "out of memory"); return -1; } if (ret == Z_DATA_ERROR) { /* deflate stream invalid */ gz_error(state, Z_DATA_ERROR, strm->msg == NULL ? "compressed data error" : strm->msg); return -1; } } while (strm->avail_out && ret != Z_STREAM_END); /* update available output and crc check value */ state->have = had - strm->avail_out; state->next = strm->next_out - state->have; strm->adler = crc32(strm->adler, state->next, state->have); /* check gzip trailer if at end of deflate stream */ if (ret == Z_STREAM_END) { if (gz_next4(state, &crc) == -1 || gz_next4(state, &len) == -1) { gz_error(state, Z_DATA_ERROR, "unexpected end of file"); return -1; } if (crc != strm->adler) { gz_error(state, Z_DATA_ERROR, "incorrect data check"); return -1; } if (len != (strm->total_out & 0xffffffffL)) { gz_error(state, Z_DATA_ERROR, "incorrect length check"); return -1; } state->how = LOOK; /* ready for next stream, once have is 0 (leave state->direct unchanged to remember how) */ } /* good decompression */ return 0; }