0
votes

I'd like to use inflate() to decompress a deflated buffer and write the result into a file. Therefore I used the code of this example. I also used the example code to deflate my buffer, which worked without problems. But when I inflate my data, the output size seems to be wrong. My file output has the properly inflated code but the end is filled up with '0xCC' until CHUNK bytes (16kB) are written. The input buffer's size is < CHUNK. The file stream is set to O_BINARY. The inner loop is run twice, once strm.avail_out == 0 and then strm.avail_out == CHUNK. That means CHUNK bytes are written, although the output's size is smaller.

#define CHUNK 16384

byte chunkBuf[CHUNK];

int inf(byte *src, size_t srcsize, FILE *dest)
{
    int ret;
    unsigned have;
    unsigned char in[CHUNK];
    unsigned long srcpos = 0;
    z_stream strm;

    /* allocate inflate state */
    strm.zalloc = Z_NULL;
    strm.zfree = Z_NULL;
    strm.opaque = Z_NULL;
    strm.avail_in = 0;
    strm.next_in = Z_NULL;
    ret = inflateInit(&strm);
    if (ret != Z_OK) {
        printf("ERR: inf: %i\n",ret);
        return ret;
    }
    /* decompress until deflate stream ends or end of file */
    do {
        if (srcsize - srcpos > CHUNK) {
            memcpy(in,src+srcpos,CHUNK);
            strm.avail_in = CHUNK;
            srcpos += CHUNK;
        } else if (srcsize - srcpos > 0) {
            memcpy(in,src+srcpos,srcsize - srcpos);
            strm.avail_in = srcsize - srcpos;
            srcpos = srcsize;
        } else {
            break;
        }

        strm.next_in = in;

        /* run inflate() on input until output buffer not full */
        do {
            strm.avail_out = CHUNK;
            strm.next_out = chunkBuf;
            ret = inflate(&strm, Z_NO_FLUSH);
            assert(ret != Z_STREAM_ERROR);  /* state not clobbered */
            switch (ret) {
            case Z_NEED_DICT:
                ret = Z_DATA_ERROR;     /* and fall through */
            case Z_DATA_ERROR:
            case Z_MEM_ERROR:
                (void)inflateEnd(&strm);
                return ret;
            }

            have = CHUNK - strm.avail_out;
            if (fwrite(chunkBuf, 1, have, dest) != have || ferror(dest)) {
                (void)inflateEnd(&strm);
                return Z_ERRNO;
            }
        } while (strm.avail_out == 0);

        /* done when inflate() says it's done */
    } while (ret != Z_STREAM_END);

    /* clean up and return */
    (void)inflateEnd(&strm);

    return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
}
1

1 Answers

1
votes

You probably gave the wrong length to deflate and compressed junk after your data.