如何用一个非常旧的 zlib 给 gzip 充气?
How to inflate a gzip with a really old zlib?
我使用的是移植了旧版本 zlib 的 PPC 平台。是否可以使用 zlib 1.1.3 来扩充使用 gzip 1.5 制作的存档?
$ 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|
我已经尝试使用此代码(其中源是指向 1f 8b
处第一个字节的指针)和三个选项 A、B 和 C 来进行 WBIT 初始化。
int ZEXPORT gunzip (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;
/* option A */
err = inflateInit(&stream);
/* option B */
err = inflateInit2(&stream, 15 + 16);
/* option C */
err = inflateInit2(&stream, -MAX_WBITS);
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;
}
选项A:
zlib inflate() 失败并出现错误 Z_DATA_ERROR。 "unknown compression method"
z_stream.avail_in = 4261640
z_stream.total_in = 1
z_stream.avail_out = 134152192
z_stream.total_out = 0
选项 B:
zlib inflateInit2_() 在第 118 行失败并显示 Z_STREAM_ERROR。
/* set window size */
if (w < 8 || w > 15)
{
inflateEnd(z);
return Z_STREAM_ERROR;
}
选项 C:
zlib inflate() 失败并出现错误 Z_DATA_ERROR。 "invalid block type"
z_stream.avail_in = 4261640
z_stream.total_in = 1
z_stream.avail_out = 134152192
z_stream.total_out = 0
您的选项 B 适用于 zlib 1.2.1 或更高版本。
对于 zlib 1.1.3,有两种方法。
使用 gzopen()
、gzread()
和 gzclose()
从文件中读取 gzip 流并解压缩到内存中。
要从内存中的 gzip 流解压缩,请使用选项 C,raw inflate,after 手动解码 gzip header。使用 crc32()
来计算解压缩数据的 CRC-32,因为你膨胀它。 inflation 完成后,手动解码 gzip 尾部,检查 CRC-32 和解压缩数据的大小。
手动解码 gzip header 和预告片很容易实现。有关 header 和预告片的说明,请参阅 RFC 1952。
我使用的是移植了旧版本 zlib 的 PPC 平台。是否可以使用 zlib 1.1.3 来扩充使用 gzip 1.5 制作的存档?
$ 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|
我已经尝试使用此代码(其中源是指向 1f 8b
处第一个字节的指针)和三个选项 A、B 和 C 来进行 WBIT 初始化。
int ZEXPORT gunzip (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;
/* option A */
err = inflateInit(&stream);
/* option B */
err = inflateInit2(&stream, 15 + 16);
/* option C */
err = inflateInit2(&stream, -MAX_WBITS);
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;
}
选项A:
zlib inflate() 失败并出现错误 Z_DATA_ERROR。 "unknown compression method"z_stream.avail_in = 4261640
z_stream.total_in = 1
z_stream.avail_out = 134152192
z_stream.total_out = 0
选项 B:
zlib inflateInit2_() 在第 118 行失败并显示 Z_STREAM_ERROR。 /* set window size */
if (w < 8 || w > 15)
{
inflateEnd(z);
return Z_STREAM_ERROR;
}
选项 C:
zlib inflate() 失败并出现错误 Z_DATA_ERROR。 "invalid block type"z_stream.avail_in = 4261640
z_stream.total_in = 1
z_stream.avail_out = 134152192
z_stream.total_out = 0
您的选项 B 适用于 zlib 1.2.1 或更高版本。
对于 zlib 1.1.3,有两种方法。
使用
gzopen()
、gzread()
和gzclose()
从文件中读取 gzip 流并解压缩到内存中。要从内存中的 gzip 流解压缩,请使用选项 C,raw inflate,after 手动解码 gzip header。使用
crc32()
来计算解压缩数据的 CRC-32,因为你膨胀它。 inflation 完成后,手动解码 gzip 尾部,检查 CRC-32 和解压缩数据的大小。
手动解码 gzip header 和预告片很容易实现。有关 header 和预告片的说明,请参阅 RFC 1952。