2012-01-07 18 views
2

gzipファイルがメモリにあり、zlibバージョン1.1.3を使用して解凍したいと思います。 Uncompress()は、ソースデータが破損していることを示す-3、Z_DATA_ERRORを返します。zlibバージョン1.1.3を使用してメモリにgzipファイルを解凍

メモリバッファが正しくあることがわかります。バッファにファイルを書き出すと、ソースのgzipファイルと同じになります。

The gzip file formatは、10バイトのヘッダー、オプションのヘッダー、データ、およびフッターがあることを示します。データの開始位置を特定し、その部分を削除することは可能ですか?私はこのトピックについて検索を行い、いくつかの人がinflateInit2()を使用するように提案しました。しかし、私のバージョンのzlibでは、その関数が奇妙にコメントアウトされています。他のオプションはありますか?

+4

バージョン1.1.3を使用する特別な理由はありますか?バージョン1.1.4は2002年3月に、最新バージョンは1.2.5になりました。 – ruakh

+0

私が使用しているバージョンはかなり古いと思いますが、これはzlibのアップデートを許可しないレガシープロジェクトです。 – gmletzkojr

答えて

0

データの開始位置を特定し、その部分を削除することは可能ですか?

Gzipでは、以下のmagic numberがあります

static const unsigned char gzipMagicBytes[] = { 0x1f, 0x8b, 0x08, 0x00 }; 

あなたはファイルストリームを読んで、このバイトを探すことができます:あなたはオフセットを持って

static const int testElemSize = sizeof(unsigned char); 
static const int testElemCount = sizeof(gzipMagicBytes); 

const char *fn = "foo.bar"; 
FILE *fp = fopen(fn, "rbR"); 
char testMagicBuffer[testElemCount] = {0}; 
unsigned long long testMagicOffset = 0ULL; 

if (fp != NULL) { 
    do { 
     if (memcmp(testMagicBuffer, gzipMagicBytes, sizeof(gzipMagicBytes)) == 0) { 
      /* we found gzip magic bytes, do stuff here... */ 
      fprintf(stdout, "gzip stream found at byte offset: %llu\n", testMagicOffset); 
      break; 
     } 
     testMagicOffset += testElemSize * testElemCount; 
     fseek(fp, testMagicOffset - testElemCount + 1, SEEK_SET); 
     testMagicOffset -= testElemCount + 1; 
    } while (fread(testMagicBuffer, testElemSize, testElemCount, fp)); 
} 

fclose(fp); 

たら、コピー&ペーストを行うことができます操作、または他のバイトを上書きするなど

1

他のzlibバージョン(1.2.7)
inflateInit2()がコメント化されている理由がわかりません。あなたは次の操作を行うことができinflateInit2を呼び出さずに

err = inflateInit(&d_stream); 
err = inflateReset2(&d_stream, 31); 

inflateReset2もinflateInitによって呼び出されます。 inflateInitの内部では、WindowBitsは15(1111バイナリ)に設定されています。しかし、gzipを動作させるには、それらを31(11111)に設定する必要があります。

理由はここにある:

inflateReset2の内部以下が行われる:ウィンドウビットは15(1111バイナリ)に設定されている場合、図2に窓ビットが設定されていれば1をもたらす

wrap = (windowBits >> 4) + 1; 

今、あなたはHEAD状態で次の行は、GZIP

if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ 
01のためのマジックナンバーとともに状態 - >ラップ値をチェック)(膨らまを呼び出した場合31(11111)

私は、メモリ内のgzip圧縮解除を行うことができた次のコードで

ので: (注:このコードは、完全なデータが解凍されることを前提とし、メモリ内にあり、解凍されたデータのバッファが十分な大きさであること)

int err; 
z_stream d_stream; // decompression stream 



d_stream.zalloc = (alloc_func)0; 
d_stream.zfree = (free_func)0; 
d_stream.opaque = (voidpf)0; 

d_stream.next_in = deflated; // where deflated is a pointer the the compressed data buffer 
d_stream.avail_in = deflatedLen; // where deflatedLen is the length of the compressed data 
d_stream.next_out = inflated; // where inflated is a pointer to the resulting uncompressed data buffer 
d_stream.avail_out = inflatedLen; // where inflatedLen is the size of the uncompressed data buffer 

err = inflateInit(&d_stream); 
err = inflateReset2(&d_stream, 31); 
err = inflateEnd(&d_stream); 

inflateInit2()のコメントはoderソリューションです。ここで直接WindowBitsを設定することができます

関連する問題