用 zlib/minizip 确定压缩块大小

Determine the compressed block size with zlib/minizip

我正在尝试制作一个跨平台 Appx 打包程序(用于 Windows 商店应用程序)。该格式只是一个带有一些元数据文件的 zip。

我需要制作一个 XML 文件,其中包含格式所需的文件哈希值。问题是它需要为每个文件的每 64KB 未压缩数据和 compressed size of such 64KB block 计算一个哈希值。 我该怎么做?

如果需要,我会直接使用 Minizip library and can also use zlib

在我看来,我需要避免压缩文件(我想避免)或跳过 Minizip 的压缩并使用 zlib 中的原始内容来压缩文件(我不熟悉 zlib 的API 了解将每个 64KB 块单独制作是否足够可行)。


TL;DR:如何判断 Zip 文件中 64KB 未压缩数据块的压缩大小?

我最终制作了 Zip 文件 "by hand" 并单独压缩块以计算它们的哈希值。

#include <zlib.h>
#define BLOCK_SIZE 65536

z_stream strm;
// Using init2 to avold the zlib header
deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY);

int step = 0.

// len is the length of the whole input file
while (len - step > 0) {
    // Get the size of this block (either 64k or the remaining of the file if less)
    long block_size = (len - step) > BLOCK_SIZE ? BLOCK_SIZE : (len - step);

    // strm_in is the input buffer for the compression
    // skipped the buffer allocation for simplicity
    for (int i = 0; i < block_size; i++) {
        strm_in[i] = input_file_buffer[step + i];
    }

    // Calculate the hash (out of the scope for this question)
    // Store in a particular structure for reference later
    BlockData bd;
    bd.hash = make_block_hash(strm_in, block_size);

    // Update the zlib stream info
    // also skipped the out buffer allocation in this sample
    strm.avail_in = block_size;
    strm.avail_out = out_buffer_size;
    strm.next_in = strm_in;
    strm.next_out = strm_out;

    // Save the total bytes for comparison later
    int total_out_before = strm.total_out; 

    // Compress (assume the out buffer size will be always enough)
    deflate(&strm, Z_FULL_FLUSH); // A Full flush here is needed for the APPX format

    // Save the compressed block in the size
    compressed_file->save_buffer(strm_out, strm.total_out - total_out_before);

    // Save the size of the compressed block
    bd.compressed_size = strm.total_out - total_out_before;

    // Store the block data in a list
    blocks_info->push(bd);

    // Move to the next block
    step += block_size;
}

// End the compressed stream
strm.avail_in = 0;
strm.avail_out = out_buffer_size;
strm.next_in = strm_in;
strm.next_out = strm_out;

int total_out_before = strm.total_out;

// Finish the stream
deflate(&strm, Z_FINISH);

// Save the compression tail to the file
compressed_file->save_buffer(strm_out, strm.total_out - total_out_before);

// Clean up
deflateEnd(&strm);

在经历了所有这些麻烦之后,我找到了一个跨平台 open source tool,它可以打包并签署 Windows 商店应用程序。可能对其他人有帮助,对认为在 Windows 之外签名是不可能的我也有帮助。