Я обновлял код проекта с версии zlib 1998 года до версии zlib 2013 года. Одна вещь, которая, казалось, изменилась, это то, что раньше был флаг "use_crc" в функции uncompress, который, похоже, пропал:
int ZEXPORT uncompress (dest, destLen, source, sourceLen, use_crc)
Bytef *dest;
uLongf *destLen;
const Bytef *source;
uLong sourceLen;
int use_crc; // <-- vanished (?)
(ОБНОВЛЕНИЕ: как указал @Joe, вероятно, это сторонняя модификация. Заголовок обновлен соответствующим образом. Остальная часть вопроса по-прежнему применима, например," как мне лучше всего сделать это с сегодняшним стандартным zlib ".)
В коде, который я изучаю, uncompress () вызывается чем-то, что деконструирует двоичный формат .zip и передает "полезную нагрузку" данных. Код передал флаг crc как 1. Если флаг не использовался, он получил бы Z_DATA_ERROR (-3). (Zlib без флага use_crc получает Z_DATA_ERROR, как если бы флаг был ложным.)
В ходе экспериментов я обнаружил, что очень маленькие файлы работают без use_crc. Затем небольшие файлы подсчета перешли в неработающие между "12345678901234"
и "123456789012345"
. Причина заключалась в следующем: это первый файл, который был спущен, а не сохранен в несжатом (при том, что zip назвал экономию «6%»)
Пытаясь заставить zlib его принять, я пробовал многое. Это включало попытку 16 + MAX_WBITS. Казалось, что ничто не обрабатывает полезную нагрузку из zip test.zip test.txt, как это было в старом коде.
Если бы я был готов вычесть единицу из моего конечного размера, я бы, казалось, смог подавить ошибочную проверку ... при потере одного байта. Вот простая тестовая программа с жестко запрограммированной минимальной полезной нагрузкой zip:
#include <stdio.h>
#include "zlib.h"
int main(int argc, char *argv[]) {
char compressed[] = { 0x78, 0x9C, 0x33, 0x34, 0x32, 0x36, 0x31, 0x35, 0x33,
0xB7, 0xB0, 0x34, 0x30, 0x04, 0xB1, 0xB8, 0x00, 0x31, 0x30, 0xB1, 0x30,
0x10, 0x00, 0x00, 0x00 }; // last 4 bytes are size (16)
char uncompressed[16 + 1]; // account for null terminator
int ret; z_stream strm;
memset(uncompressed, 'X', 16);
uncompressed[16] = '\0';
strm.zalloc = strm.zfree = strm.opaque = Z_NULL;
strm.total_out = 0;
strm.avail_in = 25;
strm.next_in = compressed;
ret = inflateInit2(&strm, MAX_WBITS /* + 16 */); // it is Z_OK
strm.avail_out = 15; // 16 gives error -3: "incorrect header check"
strm.next_out = uncompressed;
ret = inflate(&strm, Z_NO_FLUSH);
if (ret != /* Z_STREAM_END */ Z_OK) { // doesn't finish...
printf("inflate() error %d: %s\n", ret, strm.msg);
return 2;
}
inflateEnd(&strm);
printf("successful inflation: %s\n", uncompressed);
return 0;
}
Результат:
успешная инфляция: 123456789012345X
Показанные данные не сжимаются, но нам нужны все 16 байтов. (Там есть новая строка из файла, который должен быть получен.) 16 + MAX_WBITS даже этого не понять.
Есть идеи, что не так? Кажется, что никакая перестановка настроек не проходит без ошибок.
use_crc
ссылки. Возможно, это был патч к официальному zlib, сделанный какой-то третьей стороной? - person Joe   schedule 02.10.2015