问题描述
我使用的 PPC 平台移植了旧版本的 zlib。是否可以使用 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|
我已尝试使用此代码(其中 source 是指向 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。 “未知的压缩方法”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。 “无效的块类型”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,原始膨胀,之后手动解码 gzip 标头。使用
crc32()
在膨胀时计算解压缩数据的 CRC-32。膨胀完成后,手动解码 gzip 预告片,检查 CRC-32 和解压数据的大小。
gzip 头和尾的手动解码很容易实现。有关标题和预告片的说明,请参阅 RFC 1952。