At last I made it work with native zlib library
It may be not elegant enough, but my C skills are poor at the moment
Some variables are have to be global as zlib stream should be uninterrupted.
I compress the previous block as the last one should be flushed and I didn't find a way to determinate it via libcurl calls.
So if we out of easy_perform the previous ine was the last :)
All error checking are omitted for clarity
SHA1 checksum of original stream is calculated also
#define CHUNK 16384
SHA_CTX ctx;
z_stream strm;
unsigned char old_block[CHUNK];
unsigned char out[CHUNK];
unsigned have;
size_t prevBlkSize;
char firstIter;
size_t
curl_write_func(void *ptr, size_t size, size_t nmemb, void *stream)
{
//Stores the size of original data to write
size_t orig_size=size*nmemb;
if(firstIter)
{
memcpy(old_block,ptr,orig_size);
prevBlkSize=orig_size;
firstIter=0;
SHA1_Update(&ctx, ptr, orig_size);
return(orig_size);
}
//Compress old block with Z_NO_FLUSH
strm.avail_in=prevBlkSize;
strm.next_in = old_block;
do
{
strm.avail_out = CHUNK;
strm.next_out = out;
deflate(&strm, Z_NO_FLUSH);
have = CHUNK - strm.avail_out;
fwrite(out, 1, have, (FILE *) stream);
}
while (strm.avail_out == 0);
//
memcpy(old_block,ptr,orig_size);
prevBlkSize=orig_size;
SHA1_Update(&ctx, ptr, orig_size);
return (orig_size);
}
...
FILE *xva_export = fopen(xva_name, "wb");
//Prepare SHA1 and zlib
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
deflateInit(&strm, 9);
SHA1_Init(&ctx);
...
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_write_func);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, xva_export);
curl_easy_perform(curl);
curl_easy_cleanup(curl);
//Finish zlib
strm.avail_in=prevBlkSize;
strm.next_in = old_block;
do
{
strm.avail_out = CHUNK;
strm.next_out = out;
deflate(&strm, Z_FINISH);
have = CHUNK - strm.avail_out;
fwrite(out, 1, have, xva_export);
}
while (strm.avail_out == 0);
deflateEnd(&strm);
//SHA1 finish
SHA1_Final(hash, &ctx);
snprintf(sha1_name,sizeof(sha1_name),"%s.Z.sha1",xva_name);
FILE *sha1sum=fopen(sha1_name,"w");
for(int i=0; i<SHA_DIGEST_LENGTH; i++)
{
fprintf(sha1sum,"%x",hash[i]);
}
fclose(sha1sum);
fclose(xva_export);