zlib gzread function error when read .gz file? - c++

like title, here is my code:
int decompress_one_file(char *infilename, char *outfilename)
{
gzFile infile = gzopen(infilename, "rb");
FILE *outfile = fopen(outfilename, "wb");
if (!infile || !outfile) return -1;
char buffer[128] = {NULL};
int num_read = 0;
num_read = gzread(infile, buffer, sizeof(buffer)); // crash here
while (num_read > 0) {
fwrite(buffer, 1, num_read, outfile);
}
gzclose(infile);
fclose(outfile);
return 0;
}
when my console-app run to gzread(), its crash, I don't know what type of error is this?. zlib version: 1.2.11
update compress function:
int compress_one_file(char *infilename, char *outfilename)
{
FILE *infile = fopen(infilename, "rb");
gzFile outfile = gzopen(outfilename, "wb");
if (!infile || !outfile) return -1;
char inbuffer[128] = {NULL};
int num_read = 0;
unsigned long total_read = 0, total_wrote = 0;
while ((num_read = fread(inbuffer, 1, sizeof(inbuffer), infile)) > 0) {
total_read += num_read;
gzwrite(outfile, inbuffer, num_read);
}
fclose(infile);
gzclose(outfile);
return 0;
}
Error that shows up:
Anyone got an idea about this error?

I checked and it works fine at my workstation. May be here is a issue with gzipped file?
Could you show a file that give a crash?
But in any case you have a infinity loop of fwrite:
int num_read = 0;
while ((num_read = gzread(infile, buffer, sizeof(buffer))) > 0) {
while (num_read > 0) {
num_read -= fwrite(buffer, 1, num_read, outfile);
}
}

Related

zlib decompression return -3 (z_data_error)

The zlib uncompress() return -3 (z_data_error) when I decompress data.
From doc: returns Z_DATA_ERROR if the input data was corrupted or incomplete,
uncompress((Bytef*)uncompressbuffer, &uncompressbuffersize, (const Bytef*)compressbuffer, &compressbuffersize)
In another application, where I use deflate/inflate I get the same error.
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.avail_in = inputLength;
strm.next_in = (unsigned char*) inputBuffer;
ret = inflateInit(&strm);
if (ret != Z_OK)
{
delete[] uncompressedData;
return ERROR;
}
/******************************************************/
strm.avail_out = unusedData;
strm.next_out = (uncompressedData + MIN_CHUNK) - unusedData;
/* run inflate() on input until output buffer not full */
do {
ret = inflate(&strm, Z_NO_FLUSH);
assert(ret != Z_STREAM_ERROR); /* state not clobbered */
switch (ret)
{
case Z_NEED_DICT:
ret = Z_DATA_ERROR; /* and fall through */
case Z_DATA_ERROR:
case Z_MEM_ERROR:
(void)inflateEnd(&strm);
return ret;
}
} while (strm.avail_out != 0 && ret == Z_OK);
but
this error happens only with x64 version of my software. A x86 working properly. The unzipped data is intact. The buffer size of compressed and uncompressed data are correct.
Zlib is correctly compiled to x64.
What else could be causing this problem? Any hint?
Sample code with "uncompress":
#include <iostream>
#include <fstream>
#include <cstdio>
#include <vector>
#include <zlib.h>
#include <assert.h>
#include <cstdlib>
#define CHUNK 16384
const int BUFFERSIZE = 4096;
using namespace std;
void compress(FILE* fin, FILE* fout) {
char buffer[BUFFERSIZE];
int byte_read = fread(buffer, sizeof(char), BUFFERSIZE, fin);
z_stream strm;
int ret;
unsigned have;
unsigned char* tmp = new unsigned char[CHUNK];
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.next_in = (unsigned char*)buffer;
strm.avail_in = byte_read;
strm.next_out = tmp;
strm.avail_out = CHUNK;
ret = deflateInit(&strm, Z_DEFAULT_COMPRESSION);
//first loop: compress input data stream and write on RTDB file
do
{
ret = deflate(&strm, Z_NO_FLUSH);
assert(ret != Z_STREAM_ERROR);
have = BUFFERSIZE - strm.avail_out;
fwrite(tmp, sizeof(char), BUFFERSIZE, fout);
} while (strm.avail_out == 0);
//assert(strm.avail_in == 0);
//second loop: all input data consumed. Flush everything...
do
{
strm.next_out = tmp;
strm.avail_out = BUFFERSIZE;
ret = deflate(&strm, Z_FINISH);
assert(ret != Z_STREAM_ERROR);
have = BUFFERSIZE - strm.avail_out;
fwrite(tmp, sizeof(char), BUFFERSIZE, fout);
} while (ret != Z_STREAM_END);
(void)deflateEnd(&strm);
delete tmp;
}
void decompress(FILE* fin, FILE* fout) {
int status;
char buffer[BUFFERSIZE];
int byte_read = fread(buffer, sizeof(char), BUFFERSIZE, fin);
void* compressedBuffer;
void* uncompressedBuffer;
uLongf compressedBufferSize = BUFFERSIZE;
uLongf uncompressedBufferSize = BUFFERSIZE;
compressedBuffer = malloc(compressedBufferSize);
uncompressedBuffer = malloc(uncompressedBufferSize);
status = uncompress((Bytef*)uncompressedBuffer, &uncompressedBufferSize, (const Bytef*)buffer, compressedBufferSize);
fwrite(uncompressedBuffer, sizeof(char), BUFFERSIZE, fout);
cout << "Status " << status << endl;
}
int main(int argc, char *argv[]) {
//if (argc == 2)
//{
// if (strcmp(argv[1], "/?") == 0 || strcmp(argv[1], "--help") == 0)
// {
// cout << "Please give me 1 argument" << endl;
// //getchar();
// return -1;
// }
//}
//else
//{
// cout << "Please give me 1 argument" << endl;
// //getchar();
// return -1;
//}
//char *inputdata = argv[1];
//const char *inputdata = "C:\\Users\\Francesco\\source\\repos\\zlibtest\\P0000P0000_no_com-alt.rtdb";
const char *inputdata = "C:\\Users\\Francesco\\source\\repos\\zlibtest\\AAA.txt";
//const char *inputdata = "C:\\Users\\Francesco\\source\\repos\\zlibtest\\P0000P0000_no_com-alt.rtdb";
cout << inputdata << endl;
FILE *fin, *fout, *fdec;
fopen_s(&fin, inputdata, "r+");
fopen_s(&fout, "output.txt", "w+");
compress(fin, fout);
fclose(fin);
fclose(fout);
fopen_s(&fout, "output.txt", "r");
fopen_s(&fdec, "dec.txt", "w");
decompress(fout, fdec);
fclose(fout);
fclose(fdec);
}
Your first problem is that as you are using windows you must open the compressed file in binary mode otherwise it will be corrupted:
fopen_s(&fout, "output.txt", "w+b");
fopen_s(&fout, "output.txt", "rb");
if the file you are compressing isn't text or if it is text and you want to perfectly preserve it you should also open the input and dec files in binary mode.
Next in compress you confuse BUFFERSIZE and CHUNK, have = BUFFERSIZE - strm.avail_out; should be have = CHUNK - strm.avail_out;, you then need to pass have to fwrite: fwrite(tmp, sizeof(char), have, fout);.
In decompress you need to pass uncompressedBufferSize to fwrite instead of BUFFERSIZE.
Fully working code (with some additional changes to fix memory leaks):
#include <iostream>
#include <fstream>
#include <cstdio>
#include <vector>
#include <zlib.h>
#include <assert.h>
#include <cstdlib>
#include <array>
const size_t CHUNK_SIZE = 16384;
const size_t BUFFER_SIZE = 4096;
void compress(FILE* fin, FILE* fout) {
std::array<Bytef, BUFFER_SIZE> buffer;
int byte_read = fread(buffer.data(), sizeof(char), buffer.size(), fin);
z_stream strm;
int ret;
unsigned have;
std::vector<Bytef> tmp(CHUNK_SIZE);
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.next_in = buffer.data();
strm.avail_in = byte_read;
strm.next_out = tmp.data();
strm.avail_out = tmp.size();
ret = deflateInit(&strm, Z_DEFAULT_COMPRESSION);
//first loop: compress input data stream and write on RTDB file
do
{
ret = deflate(&strm, Z_NO_FLUSH);
assert(ret != Z_STREAM_ERROR);
have = tmp.size() - strm.avail_out;
fwrite(tmp.data(), sizeof(char), have, fout);
} while (strm.avail_out == 0);
//assert(strm.avail_in == 0);
//second loop: all input data consumed. Flush everything...
do
{
strm.next_out = tmp.data();
strm.avail_out = tmp.size();
ret = deflate(&strm, Z_FINISH);
assert(ret != Z_STREAM_ERROR);
have = tmp.size() - strm.avail_out;
fwrite(tmp.data(), sizeof(char), have, fout);
} while (ret != Z_STREAM_END);
(void)deflateEnd(&strm);
}
void decompress(FILE* fin, FILE* fout) {
int status;
std::array<Bytef, BUFFER_SIZE> compressedBuffer;
std::array<Bytef, BUFFER_SIZE> uncompressedBuffer;
int byte_read = fread(compressedBuffer.data(), sizeof(char), compressedBuffer.size(), fin);
uLongf compressedBufferSize = compressedBuffer.size();
uLongf uncompressedBufferSize = uncompressedBuffer.size();
status = uncompress(uncompressedBuffer.data(), &uncompressedBufferSize, compressedBuffer.data(), compressedBufferSize);
fwrite(uncompressedBuffer.data(), sizeof(char), uncompressedBufferSize, fout);
std::cout << "Status " << status << "\n";
}
int main(int argc, char* argv[]) {
const char* inputdata = "C:\\Users\\alan\\source\\repos\\ConanScratch\\main.cpp";
std::cout << inputdata << "\n";
FILE* fin, * fout, * fdec;
fopen_s(&fin, inputdata, "r+b");
if (!fin)
{
std::cout << "unable to open input\n";
return -1;
}
fopen_s(&fout, "output.txt", "w+b");
if (!fout)
{
std::cout << "unable to open output\n";
return -1;
}
compress(fin, fout);
fclose(fin);
fclose(fout);
fopen_s(&fout, "output.txt", "r+b");
if (!fout)
{
std::cout << "unable to open output\n";
return -1;
}
fopen_s(&fdec, "dec.txt", "wb");
if (!fdec)
{
std::cout << "unable to open dec\n";
return -1;
}
decompress(fout, fdec);
fclose(fout);
fclose(fdec);
}
Your code can be greatly simplified with boost::iostreams:
#include <iostream>
#include <fstream>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/device/file.hpp>
#include <boost/iostreams/filter/zlib.hpp>
int main(int argc, char* argv[])
{
{
std::ifstream input("C:\\Users\\alan\\source\\repos\\ConanScratch\\main.cpp", std::ios_base::binary);
boost::iostreams::filtering_ostream output;
output.push(boost::iostreams::zlib_compressor{});
output.push(boost::iostreams::file_sink("output.txt", std::ios_base::out | std::ios_base::binary));
output << input.rdbuf();
}
{
boost::iostreams::filtering_istream input;
input.push(boost::iostreams::zlib_decompressor{});
input.push(boost::iostreams::file_source("output.txt", std::ios_base::in | std::ios_base::binary));
std::ofstream output("dec.txt", std::ios_base::binary);
output << input.rdbuf();
}
}

What could be causing an unexpected_EOF error with libbzip2 readOpen function?

I'm following the bzip2 programming with libbzip2 instructions to make a script for compression/decompression, but I have run into issues with the reading step. Here's my code:
int decode = (argv[4][0]=='d');
FILE* f = fopen( argv[2], "rb" ); if( f==0 ) return 2;
FILE* g = fopen( argv[3], "wb" ); if( g==0 ) return 2;
int bzError;
int nBuf;
int f_len = flen(f);
byte* inp = new byte[f_len*4+1024*1024]; if( inp==0 ) return 3;
f_len = fread( inp, 1,f_len, f );
if( decode==0 ) {
int BLOCK_MULTIPLIER = atoi( argv[5] );
BZFILE *myBZ = BZ2_bzWriteOpen(&bzError, g, BLOCK_MULTIPLIER, 0, 0);
BZ2_bzWrite(&bzError, myBZ, inp, f_len);
BZ2_bzWriteClose(&bzError, myBZ, 0, NULL, NULL);
} else {
byte buf[4096];
BZFILE *myBZ = BZ2_bzReadOpen(&bzError, f, 0, 0, NULL, 0);
if (bzError != BZ_OK) {
fprintf(stderr, "E: BZ2_bzReadOpen: %d\n", bzError);
return -1;
}
while (bzError == BZ_OK) {
int nread = BZ2_bzRead(&bzError, myBZ, buf, sizeof buf);
cout<<"nread= "<<nread<<"\n";
if (bzError == BZ_OK || bzError == BZ_STREAM_END) {
size_t nwritten = fwrite(buf, 1, nread, stdout);
if (nwritten != (size_t) nread) {
fprintf(stderr, "E: short write\n");
return -1;
}
}
}
if (bzError != BZ_STREAM_END) {
fprintf(stderr, "E: bzip error after read: %d\n", bzError);
return -1;
}
BZ2_bzReadClose(&bzError, myBZ);
return 0;
}
The compression mode works fine, but if it is in decompression mode, the bzRead step fails and I get the following output from my error messages/statements:
nread = 0
E: bzip error after read: -7
Why would nread be 0? Also, the -7 represents an unexpected EOF, but how is that possible? I have tried running this on files compressed with the built in linux bzip2 as well, and gotten the same output.
Looks like you're reading the entire input file before you decide if you're decoding or not. If you are, then you try to continue reading that same input file even though you had already reached the end of the file. So you get nothing.

Stack around the variable 'fname' was corrupted

the program is to read back multiple bin files
there is an above-mentioned error happened at the end of "main" program. where did I code wrong? thank you for help
char* read_back(const char* filename)
{
FILE* pFile;
long lSize;
char* buffer;
pFile = fopen(filename, "rb");
if (pFile == NULL) { fputs("File error", stderr); exit(1); }
fseek(pFile, 0, SEEK_END);
lSize = ftell(pFile);
rewind(pFile); // set file pos at the begining
// copy the file into the buffer:
buffer = (char*)malloc(sizeof(char)*lSize);
size_t result = fread(buffer, 1, lSize, pFile);
if (result != lSize) { fputs("Reading error", stderr); exit(3); }
fclose(pFile);
return buffer;
}
int main() {
const char *fname[2] ;
fname[0] = "C:\\0_data.bin";
fname[1] = "C:\\1_data.bin";
fname[2] = "C:\\2_data.bin";
int i;
char * readback_data;
for (i = 0; i < 3; ++i)
{
readback_data=read_back(fname[i]);
}
return 0;
}
const char *fname[2] ;
This declares an array with two values, two pointers: fname[0] and fname[1].
fname[0] = "C:\\0_data.bin";
fname[1] = "C:\\1_data.bin";
fname[2] = "C:\\2_data.bin";
This attempts to put three pointers into an array that's sized only for two. That's your stack corruption, right here.

fread loses binary data

I am using fread function to read file, which I am sending via TCP. I found out, that fread doesn't read the whole file, if the file is binary. I tried everything what i found on the internet, but nothing helped. My code is:
#define BUFSIZE 1024
char buf[BUFSIZE];
FILE *file = fopen(soubor,"rb"); //I do a check which i won't write here
size_t bytes_loaded = 0;
while (!feof(file))
{
bytes_loaded = fread(buf,1,BUFSIZE,file);
if(bytes_loaded != BUFSIZE)
{
if(!feof(file))
{
for(int i = 0; i < 100;i++)
{
fseek(file,-strlen(buf),SEEK_CUR);
bytes_loaded = fread(buf,1,BUFSIZE,file);
if(bytes_loaded == BUFSIZE)
{
break;
}
else if(i == 99)
{
fprintf(stderr,"C could't read the file\n");
fclose(file);
close(client_socket);
return 1;
}
}
}
}
bytestx = send(client_socket, buf, BUFSIZE, 0);
if (bytestx < 0)
perror("ERROR in sendto");
bzero(buf, BUFSIZE);
bytes_loaded = 0;
}
Am I doing something wrong? For example that fread check...
Your whole fread() error handling is wrong, get rid of it (using strlen() on a binary buffer is wrong anyway).
In fact, you shouldn't be using feof() to control your loop. Simply call fread() in a loop until it returns < 1 on EOF or error (use feof() and ferror() to differentiate). And when it returns > 0, you need to pass that value to send instead of passing BUFSIZE.
Try something more like this:
#define BUFSIZE 1024
char buf[BUFSIZE], *pbuf;
FILE *file = fopen(soubor, "rb");
...
size_t bytes_loaded;
do
{
bytes_loaded = fread(buf, 1, BUFSIZE, file);
if (bytes_loaded < 1)
{
if ((!feof(file)) && ferror(file))
fprintf(stderr, "Couldn't read the file\n");
break;
}
pbuf = buf;
do
{
bytestx = send(client_socket, pbuf, bytes_loaded, 0);
if (bytestx < 0)
{
perror("ERROR in send");
break;
}
pbuf += bytestx;
bytes_loaded -= bytestx;
}
while (bytes_loaded > 0);
}
while (bytes_loaded == 0);
fclose(file);
...
If you are just shifting bytes from the file to the socket then you can just keep looping on the return value from std::fread which tells you how many bytes you read and then send exactly that many bytes to your send() command.
Something like this (untested) code:
if(FILE* fp = std::fopen(soubor, "rb"))
{
char buf[1024];
std::size_t bytesrx;
while((bytesrx = std::fread(0, 1, sizeof(buf), fp)) > 0)
{
int bytestx;
if((bytestx = send(client_socket, buf, bytesrx, 0) < 0))
{
// socket error
std::cout << "socket error: " << std::strerror(errno) << '\n';
return EXIT_FAILURE;
}
}
if(bytesrx < 0)
{
// file error
std::cout << "file error: " << std::strerror(errno) << '\n';
return EXIT_FAILURE;
}
}
else
{
// error opening file
}

How to decompress a .zip file into folder using zlib.h library?

I have a .zip file to unzip which contain multiple sub-folders. I am using zlib.h library function to unzip the .zip file.
#include<stdio.h>
#include<zlib.h>
#define MAX_MOI_PATH 200
#define READ_BLOCK_SIZE 1024*16
BOOL DCompressFile(char *SourceFILENAME, char *DestinationFILENAME)
{
char buffer[READ_BLOCK_SIZE];
unsigned long dwBytesRead;
unsigned long numberOfBytesWritten;
Bool status = false;
char cFilename[MAX_MOI_PATH];
int pathIndex=0;
char FileMode[4] = "w";
gzFile * FileFd = (gzFile *)gzopen (SourceFILENAME, "rb");
if (FileFd)
{
FILE* handle = fopen(DestinationFILENAME, "wb");
if(handle != NULL)
{
status = true;
while (status)
{
dwBytesRead = gzread(FileFd, buffer, READ_BLOCK_SIZE-1);
buffer[dwBytesRead] = '\0';
if (dwBytesRead)
{
status = fwrite(buffer, 1 , sizeof(buffer) , handle );
if(!status)
status = false;
else if (dwBytesRead < READ_BLOCK_SIZE)
{
break;
status = false;
}
}
}
fclose(handle);
}
gzclose (FileFd);
}
return status;
}
int main()
{
DCompressFile("/home/vivek/zlib_test/1.zip","/home/vivek/zlib_test/1");
return 0;
}
problem with this source code is, it is creating again a zip file "1.zip" with same content, not decompressing the .zip file to folder.
please help what going wrong with this?
gzip is not zip. zip is not gzip. Completely different things. You need to find a library or class that handles zip files. zlib doesn't do this by itself.
I complete this task using libarchive
static int
copy_data(struct archive *ar, struct archive *aw)
{
int r;
const void *buff;
size_t size;
#if ARCHIVE_VERSION_NUMBER >= 3000000
int64_t offset;
#else
off_t offset;
#endif
for (;;) {
r = archive_read_data_block(ar, &buff, &size, &offset);
if (r == ARCHIVE_EOF)
return (ARCHIVE_OK);
if (r != ARCHIVE_OK)
return (r);
r = archive_write_data_block(aw, buff, size, offset);
if (r != ARCHIVE_OK) {
return (r);
}
}
}
static int
extract(const char *filename)
{
struct archive *a;
struct archive *ext;
struct archive_entry *entry;
int flags;
int r;
//Select which attributes we want to restore.
flags = ARCHIVE_EXTRACT_TIME;
flags |= ARCHIVE_EXTRACT_PERM;
flags |= ARCHIVE_EXTRACT_ACL;
flags |= ARCHIVE_EXTRACT_FFLAGS;
a = archive_read_new();
archive_read_support_filter_all(a);
archive_read_support_format_all(a);
ext = archive_write_disk_new();
archive_write_disk_set_options(ext, flags);
archive_write_disk_set_standard_lookup(ext);
if ((r = archive_read_open_filename(a, filename, 16384)))
{
printf("File name %s\n",filename);
return 1;
}
for (;;) {
r = archive_read_next_header(a, &entry);
printf("%s \n",archive_entry_pathname(entry));
if (r == ARCHIVE_EOF)
break;
if (r < ARCHIVE_OK)
{
fprintf(stderr, "%s\n", archive_error_string(a));
printf("Error1 : %s\n",archive_error_string(a));
if (r < ARCHIVE_WARN)
return 1;
}
r = archive_write_header(ext, entry);
if (r < ARCHIVE_OK){
fprintf(stderr, "%s\n", archive_error_string(ext));
printf("Error2 : %s\n",archive_error_string(ext));
}
else if (archive_entry_size(entry) > 0) {
r = copy_data(a, ext);
if (r < ARCHIVE_OK){
fprintf(stderr, "%s\n", archive_error_string(ext));
printf("Error3 : %s\n",archive_error_string(ext));
}
if (r < ARCHIVE_WARN)
return 1;
}
r = archive_write_finish_entry(ext);
if (r < ARCHIVE_OK){
fprintf(stderr, "%s\n", archive_error_string(ext));
printf("Error4 : %s\n",archive_error_string(ext));
}
if (r < ARCHIVE_WARN)
return 1;
}
archive_read_close(a);
archive_read_free(a);
archive_write_close(ext);
archive_write_free(ext);
return 0;
}
int main()
{
extract("/home/sanjay/zlib_test/FileDownload.zip");
return 0;
}