0

I have a gzip file sample, with standard gzip header 1F 8B 08 00 ..., when I inflate it with inflate* functions in zlib, the output is only 11 bytes(in fact the output should be about 4KB), but when I decompress it with gz* functions, it produce the correct output, the code:

  1. using gz* (this can produce correct output):

    #define CHUNK 10240
    int gz_decompress(const char *path) {
        gzFile f = gzopen(path, "rb");
        if(!f)
            return -1;
    
        unsigned char result[CHUNK];
        int bytes_read = gzread(f, result, CHUNK);
        if(bytes_read < CHUNK)
            if(!gzeof(f))
                return -2;
        gzclose (f);
        return 0;
    }
    
  2. using inflate* (output is only 11 bytes):

    #define CHUNK 10240
    int inf(FILE *source)
    {
        int ret;
        unsigned have;
        z_stream strm;
        unsigned char in[CHUNK];
        unsigned char out[CHUNK];
    
        /* 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);
        ret = inflateInit2(&strm, 16 + 15);
        if (ret != Z_OK)
            return ret;
    
        /* decompress until deflate stream ends or end of file */
        do {
            strm.avail_in = fread(in, 1, CHUNK, source);
            if (strm.avail_in == 0)
                break;
            strm.next_in = in;
    
            /* run inflate() on input until output buffer not full */
            do {
                strm.avail_out = CHUNK;
                strm.next_out = out;
                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;
            } 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;
    }
    

In fact, the second snippet comes from the official zlib usage example zpipe.c, I changed only the invocation of inflateInit(&strm); to inflateInit2(&strm, 16 + 15); according to this zlib gzip discussion, but now I have no idea why it fails, anyone could help?

Community
  • 1
  • 1
Kelvin Hu
  • 1,299
  • 16
  • 31

1 Answers1

0

Per your comment, inf() is returning Z_OK, which means that the gzip stream is being successfully decompressed and verified.

What do you mean "output is only 11 bytes"? Your inf() function can produce no output at all.

Mark Adler
  • 101,978
  • 13
  • 118
  • 158
  • Sorry for reply late as the past two days are weekends, I do open the file with `binary` option, and `inf()` returns `Z_OK`, whose value is 0, I have debugged within this function, there is no any error. – Kelvin Hu Jul 29 '13 at 02:30
  • Yes, I do agree with you, it should output nothing, but in fact it produced the output with 11 bytes, every byte is 0. I pasted the sample file here: http://www.filehostfree.com/?d=51F605CA1, really appreciate if you could have a test on it. – Kelvin Hu Jul 29 '13 at 06:07
  • I don't have time to debug your code. You can count the bytes generated in `inf()` and/or write them out to check that the decompression is taking place correctly. Your 11 bytes are coming from somewhere else entirely, since your `inf()` as shown produces no output. – Mark Adler Jul 29 '13 at 16:50
  • Sorry that my comment is not clear: the **output**, I do NOT mean it is the output of `inf()`, it does produce nothing; I mean the `out` variable defined inside `inf()`, when debugging the program, the `out` variable holds 11 bytes of zero. However, thanks for your help, I will avoid `inf*` functions and use `gz*` to solve the problem. – Kelvin Hu Jul 30 '13 at 04:47
  • Your statement again makes no sense. `out` is a pointer. `have` indicates how much data is at `out` on each inner loop. You need to add up the values of `have` over the loops to determine how much data was produced. Or write out `have` bytes each time to a file and see how big the file is at the end. See the `fwrite` in the original [zpipe.c](http://zlib.net/zlib_how.html). – Mark Adler Jul 30 '13 at 13:32
  • I'm sorry that this program is not very logical, but I just use it to debug (this is not production code), step into the function, and trace every variable's state. I know you are warring about that the second loop may overwrite the first loop' data in `out`, but result is, both loops are only executed once, there is no change for a second loop, and the the first loop produces 11 bytes into `out`. – Kelvin Hu Aug 02 '13 at 05:02
  • What is `have` after that? – Mark Adler Aug 02 '13 at 06:33
  • `have` is 11, the result size. – Kelvin Hu Aug 05 '13 at 09:33
  • You need to show the entire program being run, and the data it is fed. – Mark Adler Aug 05 '13 at 15:36