如何 zlib 膨胀 gzip/deflate 档案
how to zlib inflate a gzip/deflate archive
我有一个用 gzip 1.5 编码的存档。我无法使用 C zlib 库对其进行解码。 zlib inflate()
return EC -3 stream.msg = "未知压缩方法".
$ gzip --list --verbose vmlinux.z
method crc date time compressed uncompressed ratio uncompressed_name
defla 12169518 Apr 29 13:00 4261643 9199404 53.7% vmlinux
文件的前 32 个字节是:
00000000 1f 8b 08 08 29 f4 8a 60 00 03 76 6d 6c 69 6e 75 |....)..`..vmlinu|
00000010 78 00 ec 9a 7f 54 1c 55 96 c7 6f 75 37 d0 fc 70 |x....T.U..ou7..p|
我看到前 18 个字节是 RFC-1952 gzip header。
在 NULL 之后,我希望下一个字节是 RFC-1951 deflate or RFC-1950 zlib(我不确定是哪个)
因此,我向 zlib inflate() 传递一个 z_stream:next_in 指向字节 @0x12。
如果这是压缩编码,那么我希望下一个字节 @0x12 是 0aabbbbb(BFINAL=0 和 BTYPE=一些压缩)
如果这是 zlib 编码的,我希望下一个字节 @0x12 采用 0aaa1000 bbbccccc
的形式
相反,我看到了 @0x12 EC = 1110 1100
这两个都不适合。
对于我的代码,我采用了 uncompress()
代码并使用适合我的环境的分配器对其进行了轻微修改,并使用 window 位(包括 15+16
、-MAX_WBITS
, 和 MAX_WBITS
).
int ZEXPORT unzip (dest, destLen, source, sourceLen)
Bytef *dest;
uLongf *destLen;
const Bytef *source;
uLong sourceLen;
{
z_stream stream;
int err;
stream.next_in = (Bytef*)source;
stream.avail_in = (uInt)sourceLen;
/* Check for source > 64K on 16-bit machine: */
if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
stream.next_out = dest;
stream.avail_out = (uInt)*destLen;
if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
stream.zalloc = (alloc_func)my_alloc;
stream.zfree = (free_func)my_free;
/*err = inflateInit(&stream);*/
err = inflateInit2(&stream, 15 + 16);
if (err != Z_OK) return err;
err = inflate(&stream, Z_FINISH);
if (err != Z_STREAM_END) {
inflateEnd(&stream);
return err == Z_OK ? Z_BUF_ERROR : err;
}
*destLen = stream.total_out;
err = inflateEnd(&stream);
return err;
}
如何更正我对此文件的解码?
假设 my_alloc
和 my_free
做他们需要做的事情,那应该可以正常工作。您应该验证您实际上正在向 unzip()
提供您认为正在提供的数据。你给它的数据需要以 1f 8b
.
开头
(旁注:“unzip”是该函数的糟糕名称。它不解压缩,因为 zip 是一种与 gzip 或 zlib 完全不同的格式。“gunzip”或“ungzip”是合适的。)
您正在以错误的顺序手动读取 deflate 流中的位。最低有效位在前。 ec
的低三位是100
,表示非最后一个动态块。 0
用于非最后,然后 10
用于动态。
您可以使用 infgen 反汇编 deflate 流。所提供的 14 个字节的输出是动态块的初始部分:
dynamic
count 286 27 16
code 0 5
code 2 7
code 3 7
code 4 5
code 5 5
code 6 4
code 7 4
code 8 2
code 9 3
code 10 2
code 11 4
code 12 4
code 16 7
code 17 7
lens 4 6 7 7 7 8 8 8 7 8
repeat 3
lens 10
我有一个用 gzip 1.5 编码的存档。我无法使用 C zlib 库对其进行解码。 zlib inflate()
return EC -3 stream.msg = "未知压缩方法".
$ gzip --list --verbose vmlinux.z
method crc date time compressed uncompressed ratio uncompressed_name
defla 12169518 Apr 29 13:00 4261643 9199404 53.7% vmlinux
文件的前 32 个字节是:
00000000 1f 8b 08 08 29 f4 8a 60 00 03 76 6d 6c 69 6e 75 |....)..`..vmlinu|
00000010 78 00 ec 9a 7f 54 1c 55 96 c7 6f 75 37 d0 fc 70 |x....T.U..ou7..p|
我看到前 18 个字节是 RFC-1952 gzip header。 在 NULL 之后,我希望下一个字节是 RFC-1951 deflate or RFC-1950 zlib(我不确定是哪个)
因此,我向 zlib inflate() 传递一个 z_stream:next_in 指向字节 @0x12。
如果这是压缩编码,那么我希望下一个字节 @0x12 是 0aabbbbb(BFINAL=0 和 BTYPE=一些压缩)
如果这是 zlib 编码的,我希望下一个字节 @0x12 采用 0aaa1000 bbbccccc
的形式相反,我看到了 @0x12 EC = 1110 1100
这两个都不适合。
对于我的代码,我采用了 uncompress()
代码并使用适合我的环境的分配器对其进行了轻微修改,并使用 window 位(包括 15+16
、-MAX_WBITS
, 和 MAX_WBITS
).
int ZEXPORT unzip (dest, destLen, source, sourceLen)
Bytef *dest;
uLongf *destLen;
const Bytef *source;
uLong sourceLen;
{
z_stream stream;
int err;
stream.next_in = (Bytef*)source;
stream.avail_in = (uInt)sourceLen;
/* Check for source > 64K on 16-bit machine: */
if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
stream.next_out = dest;
stream.avail_out = (uInt)*destLen;
if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
stream.zalloc = (alloc_func)my_alloc;
stream.zfree = (free_func)my_free;
/*err = inflateInit(&stream);*/
err = inflateInit2(&stream, 15 + 16);
if (err != Z_OK) return err;
err = inflate(&stream, Z_FINISH);
if (err != Z_STREAM_END) {
inflateEnd(&stream);
return err == Z_OK ? Z_BUF_ERROR : err;
}
*destLen = stream.total_out;
err = inflateEnd(&stream);
return err;
}
如何更正我对此文件的解码?
假设 my_alloc
和 my_free
做他们需要做的事情,那应该可以正常工作。您应该验证您实际上正在向 unzip()
提供您认为正在提供的数据。你给它的数据需要以 1f 8b
.
(旁注:“unzip”是该函数的糟糕名称。它不解压缩,因为 zip 是一种与 gzip 或 zlib 完全不同的格式。“gunzip”或“ungzip”是合适的。)
您正在以错误的顺序手动读取 deflate 流中的位。最低有效位在前。 ec
的低三位是100
,表示非最后一个动态块。 0
用于非最后,然后 10
用于动态。
您可以使用 infgen 反汇编 deflate 流。所提供的 14 个字节的输出是动态块的初始部分:
dynamic
count 286 27 16
code 0 5
code 2 7
code 3 7
code 4 5
code 5 5
code 6 4
code 7 4
code 8 2
code 9 3
code 10 2
code 11 4
code 12 4
code 16 7
code 17 7
lens 4 6 7 7 7 8 8 8 7 8
repeat 3
lens 10