Home > Archive > Compression > March 2007 > Zlib inflate() returns "invalid header check" - help please....
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
Zlib inflate() returns "invalid header check" - help please....
|
|
| chrosciu@poczta.onet.pl 2007-03-08, 6:56 pm |
| Hello
I am trying to write simple program using zlib, that decompress zip
files. It's more or less the same as an example on zlib page:
#include <stdio.h>
#include <assert.h>
#include "zlib.h"
#define CHUNK 8192
/* Decompress from file source to file dest until stream ends or EOF.
inf() returns Z_OK on success, Z_MEM_ERROR if memory could not be
allocated for processing, Z_DATA_ERROR if the deflate data is
invalid or incomplete, Z_VERSION_ERROR if the version of zlib.h and
the version of the library linked do not match, or Z_ERRNO if there
is an error reading or writing the files. */
static int inf(FILE *source, FILE *dest)
{
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);
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 (ferror(source)) {
(void)inflateEnd(&strm);
return Z_ERRNO;
}
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;
if (fwrite(out, 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;
}
int main()
{
FILE* in = fopen("/mnt/sdb3/file2.zip", "r");
if (in != NULL) {
FILE* out = fopen("/mnt/sdb3/mhp.gif", "w");
if (out != NULL) {
int rv = inf(in, out);
if (rv == Z_OK) {
printf("[ZIP-TEST] Success\n");
} else {
printf("[ZIP-TEST] Failure\n");
}
fclose(out);
}
fclose(in);
}
return 0;
}
But inflate() function over and over again returns (-3) - "invalid
header check". What am I doing wrong? What should I pass as an input
stream to inflate() ?
a) whole file 'file2.zip'
b) whole entry 'mhp.gif' in file 'file2.zip' (with header) ?
c) only 'mhp.gif' data (without entry header?)
File 'file2.zip' contains 2 files inside: 'mhp.gif' and 'smiley.gif'.
'smiley.gif' is not deflated and I can extract it without problems
from archive.
I put the file2.zip on address:
http://master.sigmy.pl/file2.zip
Any help will be appreciated....
Best regards
Chrosciu
| |
| Mark Adler 2007-03-08, 9:55 pm |
| On Mar 8, 7:38 am, chros...@poczta.onet.pl wrote:
> I am trying to write simple program using zlib, that decompress zip files.
You can do that (assuming that the zip entries use the deflate
compression method), but you need to decode the zip headers and
trailers. zlib is normally expecting a zlib header and trailer, which
is different.
The zip format is specified here:
http://www.pkware.com/documents/casestudies/APPNOTE.TXT
with some more elaboration in the current Info-ZIP application note
found here:
ftp://sunsite.icm.edu.pl/pub/unix/a...g/info-zip/doc/
Once you find where the compressed data is in the file format (it's
relatively easy), zlib will provide raw inflate decompression for
method 8 entries. Read zlib.h for how to invoke raw inflate.
Mark
| |
| chrosciu@poczta.onet.pl 2007-03-09, 3:56 am |
|
> Once you find where the compressed data is in the file format (it's
> relatively easy), zlib will provide raw inflate decompression for
> method 8 entries. Read zlib.h for how to invoke raw inflate.
>
> Mark
But I have already done some parsing according to the ZIP file
specification as below:
1) I've found first file entry iz ZIP file
2) I've read first 26 bytes of entry (this is fixed entry header
length) and parsed it.
Parsing results were:
- compressionMethod = 8 (so file is deflated)
- fileNameLen = 7 (this is ok, file name is 'mhp.gif')
- extraFieldLen = 0
3) I've also read 7 bytes as fileName
4) extraFieldLen is 0, so there is no need to skip extraBytes
So I thought that after 26 + 7 bytes should be the beginning of zlib
stream but it isn't - the first two bytes (CMF and FLG) do not pass
the condition:
(CMF*256 + FLG) is a multiple of 31
When I tried this method of parsing on second file entry in ZIP that
is not deflated, all worked fine (stream after 26 bytes + fileNameLen
was correct GIF image)
So I'm renewing my question - what am I doing wrong ? What have I
forgotten about ?
Best regards
Chrosciu
| |
| Mark Adler 2007-03-09, 3:56 am |
| On Mar 9, 12:21 am, chros...@poczta.onet.pl wrote:
> So I thought that after 26 + 7 bytes should be the beginning of zlib
> stream but it isn't
As I said, the compressed data is not a zlib stream -- it is a raw
deflate stream. Please read zlib.h for how to perform a raw inflate.
Mark
| |
| chrosciu@poczta.onet.pl 2007-03-09, 7:56 am |
| On 9 Mar, 10:11, "Mark Adler" <mad...@alumni.caltech.edu> wrote:
> On Mar 9, 12:21 am, chros...@poczta.onet.pl wrote:
>
>
> As I said, the compressed data is not a zlib stream -- it is a raw
> deflate stream. Please read zlib.h for how to perform a raw inflate.
>
> Mark
Mark, as you said I used inflateInit2() instead of inflateInit() and
now all works fine. Thank you very much for help!
Best regards,
Chrosciu
|
|
|
|
|