• MTK Logo 逆向解析之 rawx 全解压


    紧接上一篇

    MTK Logo 逆向解析之 bin 转 rawx

    查看 zpipe 源码发现压缩使用 zlib 算法,其中也包含了解压的代码,但直接执行发现并不好使,有bug。很明显 mtk

    并没有真正用过解压,那就需要我们自己来修复一下了,总比没有代码需要我们自己新写容易些。

    知识储备,关于 zlib 使用介绍可以参考这篇

    第三方库介绍——zlib库

    对 zlib 有一定认知后,我们就来看看 zpipe 源码

    一、分析源码

    主看 main 函数,一开始做了参数类型判断,参数一 -l 就走 compress 逻辑,否则就 decompress 逻辑

    源码中提示的执行指令为 compress -l 9 logo.raw battery.raw

    input 对应 battery.raw output 对应 logo.raw

    根据实际传参数量申请大小为 filenum*4 的 unsigned int pinfo ,然后将数据全部初始化为 0 memset((void)pinfo, 0, sizeof(int)*filenum);

    关键代码来了

    if(sizeof(int)filenum != fwrite(pinfo, 1, filenumsizeof(int), output)) 将文件数量数据写入 output 头部

    pinfo[pinfo[0]+2]=ftell(output); 将指针移动到头部数据后一位,同时 pinfo[2] 存储头部数据大小

    if (Z_OK != def(input, output, level)) 执行压缩算法,压缩数据跟在头部数据后面
    {
    ret = -2;
    goto done;
    }
    pinfo[0] = pinfo[0]+1; 记录压缩了几次

    for (i = 5; i < argc; i++)
    {
    fclose(input);

    input = fopen(argv[i], "rb");  重新赋值input,重复上面核心逻辑
    
    pinfo[pinfo[0]+2]=ftell(output);
    if (Z_OK != def(input, output, level)) 
    {
    	fprintf(stderr, "compress error\n");
    	ret = -2;
    	goto done;
    }
    pinfo[0] = pinfo[0]+1;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    }
    done:
    fseek(output, 0L, SEEK_END); 文件指针移动到末尾
    pinfo[1] = ftell(output); 获取 output 完整数据
    fseek(output, 0L, SEEK_SET); 恢复文件指针位置
    fwrite(pinfo, 1, filenum*sizeof(int), output); 写入完整数据

    假如执行指令为 ./zpipe -l 9 log.raw wxganl_bat_animation_01.raw wxganl_bat_animation_02.raw wxganl_bat_animation_03.raw

    压缩过程为
    wxganl_bat_animation_01.raw --> log.raw
    wxganl_bat_animation_02.raw --> log.raw
    wxganl_bat_animation_03.raw --> log.raw

    pinfo[0]=压缩次数 pinfo[1]=第一次压缩后数据大小 pinfo[2]=要压缩文件数量大小 pinfo[3]=第一次压缩后数据大小 pinfo[4]=第一次压缩后数据大小

    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <assert.h>
    #include "zlib.h"
    
    #if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__)
    #  include <fcntl.h>
    #  include <io.h>
    #  define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
    #else
    #  define SET_BINARY_MODE(file)
    #endif
    
    #define CHUNK 16384
    
    /* Compress from file source to file dest until EOF on source.
       def() returns Z_OK on success, Z_MEM_ERROR if memory could not be
       allocated for processing, Z_STREAM_ERROR if an invalid compression
       level is supplied, Z_VERSION_ERROR if the version of zlib.h and the
       version of the library linked do not match, or Z_ERRNO if there is
       an error reading or writing the files. */
    int def(FILE *source, FILE *dest, int level)
    {
    	int ret, flush;
    	unsigned have;
    	z_stream strm;
    	unsigned char in[CHUNK];
    	unsigned char out[CHUNK];
    
    	/* allocate deflate state */
    	strm.zalloc = Z_NULL;
    	strm.zfree = Z_NULL;
    	strm.opaque = Z_NULL;
    	ret = deflateInit(&strm, level);
    	if (ret != Z_OK)
    		return ret;
    
    	/* compress until end of file */
    	do 
    	{
    		strm.avail_in = fread(in, 1, CHUNK, source);
    		if (ferror(source)) 
    		{
    			(void)deflateEnd(&strm);
    			return Z_ERRNO;
    		}
    		flush = feof(source) ? Z_FINISH : Z_NO_FLUSH;
    		strm.next_in = in;
    
    		/* run deflate() on input until output buffer not full, finish
    		   compression if all of source has been read in */
    		do 
    		{
    			strm.avail_out = CHUNK;
    			strm.next_out = out;
    			ret = deflate(&strm, flush);    /* no bad return value */
    			assert(ret != Z_STREAM_ERROR);  /* state not clobbered */
    			have = CHUNK - strm.avail_out;
    			if (fwrite(out, 1, have, dest) != have || ferror(dest)) 
    			{
    				(void)inflateEnd(&strm);
    				return Z_ERRNO;
    			}
    		} while (strm.avail_out == 0);
    		assert(strm.avail_in == 0);     /* all input will be used */
    
    		/* done when last data in file processed */
    	} while (flush != Z_FINISH);
    	assert(ret == Z_STREAM_END);        /* stream will be complete */
    
    	/* clean up and return */
    	(void)deflateEnd(&strm);
    	return Z_OK;
    }
    
    /* Decompress from file source to file dest until stream ends or EOF.
       inf() returns Z_OK on success, Z_MEM_ERROR if memory could not be
       allocated for processing, Z_DATA_ERROR if the deflate data is
       invalid or incomplete, Z_VERSION_ERROR if the version of zlib.h and
       the version of the library linked do not match, or Z_ERRNO if there
       is an error reading or writing the files. */
    int inf(FILE *source, FILE *dest)
    {
    	int ret;
    	unsigned int have;
    	z_stream strm;
    	unsigned char in[CHUNK];
    	unsigned char out[CHUNK];
    
    	/* allocate inflate state */
    	strm.zalloc = Z_NULL;
    	strm.zfree = Z_NULL;
    	strm.opaque = Z_NULL;
    	strm.avail_in = 0;
    	strm.next_in = Z_NULL;
    	ret = inflateInit(&strm);
    	if (ret != Z_OK)
    		return ret;
    
    	/* decompress until deflate stream ends or end of file */
    	do 
    	{
    		strm.avail_in = fread(in, 1, CHUNK, source);
    		if (ferror(source)) {
    			(void)inflateEnd(&strm);
    			return Z_ERRNO;
    		}
    		if (strm.avail_in == 0)
    			break;
    		strm.next_in = in;
    
    		/* run inflate() on input until output buffer not full */
    		do 
    		{
    			strm.avail_out = CHUNK;
    			strm.next_out = out;
    			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;
    			}
    
    			have = CHUNK - strm.avail_out;
    			if (fwrite(out, 1, have, dest) != have || ferror(dest)) 
    			{
    				(void)inflateEnd(&strm);
    				return Z_ERRNO;
    			}
    		} while (strm.avail_out == 0);
    
    		/* done when inflate() says it's done */
    	} while (ret != Z_STREAM_END);
    
    	/* clean up and return */
    	(void)inflateEnd(&strm);
    	return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
    }
    
    /* report a zlib or i/o error */
    void zerr(int ret)
    {
    	fputs("zpipe: ", stderr);
    	switch (ret) 
    	{
    		case Z_ERRNO:
    			if (ferror(stdin))
    				fputs("error reading stdin\n", stderr);
    			if (ferror(stdout))
    				fputs("error writing stdout\n", stderr);
    			break;
    		case Z_STREAM_ERROR:
    			fputs("invalid compression level\n", stderr);
    			break;
    		case Z_DATA_ERROR:
    			fputs("invalid or incomplete deflate data\n", stderr);
    			break;
    		case Z_MEM_ERROR:
    			fputs("out of memory\n", stderr);
    			break;
    		case Z_VERSION_ERROR:
    			fputs("zlib version mismatch!\n", stderr);
    	}
    }
    
    /* compress or decompress from stdin to stdout */
    int process(int argc, char **argv)
    {
    	int ret;
    
    	/* avoid end-of-line conversions */
    	SET_BINARY_MODE(stdin);
    	SET_BINARY_MODE(stdout);
    
    	/* do compression if no arguments */
    	if (argc == 1) 
    	{
    		ret = def(stdin, stdout, Z_DEFAULT_COMPRESSION);
    		if (ret != Z_OK)
    			zerr(ret);
    		return ret;
    	}
    
    	/* do decompression if -d specified */
    	else if (argc == 2 && strcmp(argv[1], "-d") == 0) 
    	{
    		ret = inf(stdin, stdout);
    		if (ret != Z_OK)
    			zerr(ret);
    		return ret;
    	}
    
    	/* otherwise, report usage */
    	else 
    	{
    		fputs("zpipe usage: zpipe [-d] < source > dest\n", stderr);
    		return 1;
    	}
    }
    
    int main(int argc, char **argv)
    {
    	int ret = 0;
    	int i;
    	FILE *input, *output;
    	if (argc < 4 || (strcmp(argv[1], "-l") && strcmp(argv[1], "-d"))) 
    	{
    		printf("[Usage] compress -l n output input1 [input2]\n");
    		printf("Example: compress -l 9 logo.raw battery.raw\n");
    		return -1;
    	}
    
    	// compress
    	if(!strcmp(argv[1], "-l"))
    	{
    		char *ptemp;
    		unsigned int *pinfo;
    		int level = -1;
    		int filenum = argc - 2;
    		level = atoi(argv[2]);
    
    		input = fopen(argv[4], "rb");
    		output = fopen(argv[3], "wb");
    		ptemp = (char*)malloc(1024*1024);
    		pinfo = (unsigned int*)malloc(filenum*sizeof(int));
    		if(input < 0 || output < 0 || ptemp == NULL || pinfo == NULL)
    		{
    			fprintf(stderr, "open file and allocate temp buffer fail\n");
    			fprintf(stderr, "input = %d, output = %d, ptemp = 0x%08x, pinfo = 0x%08x\n", input, output, ptemp, pinfo);
    			ret = -1;
    			goto done;
    		}
    
    		// structre of pinfo:
    		// pinfo[0] ==> size of pinfo 
    		// pinfo[1] ==> offset of zip chunk[1]
    		// pinfo[2] ==> offset of zip chunk[2]
    		// ...
    		// pinfo[n] ==> offset of zip chunk[n]
    		// "offset" is the distance from the begining of the file, not the zip chunk
    		memset((void*)pinfo, 0, sizeof(int)*filenum);
    		// write information header to output first
    		if(sizeof(int)*filenum != fwrite(pinfo, 1, filenum*sizeof(int), output))
    		{
    			ret = -2;
    			goto done;
    		}
    
    		pinfo[pinfo[0]+2]=ftell(output);
    		if (Z_OK != def(input, output, level)) 
    		{
    			ret = -2;
    			goto done;
    		}
    		pinfo[0] = pinfo[0]+1;
    
    		for (i = 5; i < argc; i++) 
    		{
    			fclose(input);
    
    			input = fopen(argv[i], "rb");
    			pinfo[pinfo[0]+2]=ftell(output);
    			if (Z_OK != def(input, output, level)) 
    			{
    				fprintf(stderr, "compress error\n");
    				ret = -2;
    				goto done;
    			}
    			pinfo[0] = pinfo[0]+1;
    		}
    
    done:
    		fseek(output, 0L, SEEK_END);
    		pinfo[1] = ftell(output);
    		fseek(output, 0L, SEEK_SET);
    		fwrite(pinfo, 1, filenum*sizeof(int), output);
    
    		fclose(input);
    		fclose(output);
    		free(ptemp);
    		free(pinfo);
    
    		return ret;
    	}
    	// decompress
    	else
    	{
    		unsigned int temp;
    		unsigned int *pinfo;
    		char outputfilename[256];
    		input = fopen(argv[3], "rb");
    		if(input < 0)
    		{
    			printf("open file fail\n");
    			printf("input = %d\n", input);
    			ret = -1;
    			goto done2;
    		}
    
    		fread(&temp, 1, sizeof(int), input);
    		printf("temp=%d\n", temp);
    		pinfo = malloc(temp*sizeof(int));
    		if(pinfo == NULL)
    		{
    			printf("allocate pinfo failed\n");
    			ret = -1;
    			goto done2;
    		}
    
    		fread(pinfo, 1, temp*sizeof(int), input);
    
    		for(i=0;i<temp;i++)
    			printf("pinfo[%d]=%d\n", i, pinfo[i]);
    
    		for(i = 0;i < temp;i++)
    		{
    			sprintf(outputfilename, "%d_%s", i, argv[2]);
    			output = fopen(outputfilename, "wb");
    			if(output < 0)
    			{
    				printf("create output file %s fail\n", outputfilename);
    				goto done2;
    			}
    
    			fseek(input, pinfo[i], SEEK_SET);
    			if(Z_OK != inf(input, output))
    			{
    				printf("decompress error\n");
    				ret = -2;
    				goto done2;
    			}
    
    			fclose(output);
    			output = 0;
    		}
    done2:
    		fclose(input);
    		if(output) fclose(output);
    		return ret;
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311
    • 312
    • 313
    • 314
    • 315
    • 316
    • 317
    • 318
    • 319
    • 320
    • 321
    • 322
    • 323
    • 324
    • 325
    • 326
    • 327
    • 328
    • 329
    • 330
    • 331
    • 332
    • 333
    • 334
    • 335
    • 336
    • 337
    • 338
    • 339
    • 340
    • 341
    • 342
    • 343
    • 344
    • 345
    • 346
    • 347
    • 348

    二、改造源码

    直接执行解压指令 ./zpipe -d xx ./logo.raw 会报错 decompress error

    经过分析是解压文件数量计算不对导致循环出错,结合上面的压缩过程结论,

    需要跳过包含 pinfo[x]=要压缩文件数量大小 无效数据

    然后我们增加参数 -d 判断, xx 就是解压后文件命名,最终会得到 0_xx.raw 1_xx.raw 等

    可以通过文件 md5 指令比对压缩前原文件和解压后的文件

    
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdint.h>
    #include <string.h>
    #include <assert.h>
    #include <zlib.h>
    
    #if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__)
    #  include <fcntl.h>
    #  include <io.h>
    #  define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
    #else
    #  define SET_BINARY_MODE(file)
    #endif
    
    #define CHUNK 16384
    
    /* Compress from file source to file dest until EOF on source.
       def() returns Z_OK on success, Z_MEM_ERROR if memory could not be
       allocated for processing, Z_STREAM_ERROR if an invalid compression
       level is supplied, Z_VERSION_ERROR if the version of zlib.h and the
       version of the library linked do not match, or Z_ERRNO if there is
       an error reading or writing the files. */
    int def(FILE *source, FILE *dest, int level)
    {
    	int ret, flush;
    	unsigned have;
    	z_stream strm;
    	unsigned char in[CHUNK];
    	unsigned char out[CHUNK];
    
    	/* allocate deflate state */
    	strm.zalloc = Z_NULL;
    	strm.zfree = Z_NULL;
    	strm.opaque = Z_NULL;
    	ret = deflateInit(&strm, level);
    	if (ret != Z_OK)
    		return ret;
    
    	/* compress until end of file */
    	do 
    	{
    		strm.avail_in = fread(in, 1, CHUNK, source);
    		if (ferror(source)) 
    		{
    			(void)deflateEnd(&strm);
    			return Z_ERRNO;
    		}
    		flush = feof(source) ? Z_FINISH : Z_NO_FLUSH;
    		strm.next_in = in;
    
    		/* run deflate() on input until output buffer not full, finish
    		   compression if all of source has been read in */
    		do 
    		{
    			strm.avail_out = CHUNK;
    			strm.next_out = out;
    			ret = deflate(&strm, flush);    /* no bad return value */
    			assert(ret != Z_STREAM_ERROR);  /* state not clobbered */
    			have = CHUNK - strm.avail_out;
    			if (fwrite(out, 1, have, dest) != have || ferror(dest)) 
    			{
    				(void)inflateEnd(&strm);
    				return Z_ERRNO;
    			}
    		} while (strm.avail_out == 0);
    		assert(strm.avail_in == 0);     /* all input will be used */
    
    		/* done when last data in file processed */
    	} while (flush != Z_FINISH);
    	assert(ret == Z_STREAM_END);        /* stream will be complete */
    
    	/* clean up and return */
    	(void)deflateEnd(&strm);
    	return Z_OK;
    }
    
    /* Decompress from file source to file dest until stream ends or EOF.
       inf() returns Z_OK on success, Z_MEM_ERROR if memory could not be
       allocated for processing, Z_DATA_ERROR if the deflate data is
       invalid or incomplete, Z_VERSION_ERROR if the version of zlib.h and
       the version of the library linked do not match, or Z_ERRNO if there
       is an error reading or writing the files. */
    int inf(FILE *source, FILE *dest)
    {
    	int ret;
    	unsigned int have;
    	z_stream strm;
    	unsigned char in[CHUNK];
    	unsigned char out[CHUNK];
    
    	/* allocate inflate state */
    	strm.zalloc = Z_NULL;
    	strm.zfree = Z_NULL;
    	strm.opaque = Z_NULL;
    	strm.avail_in = 0;
    	strm.next_in = Z_NULL;
    	ret = inflateInit(&strm);
    	if (ret != Z_OK)
    		return ret;
    
    	/* decompress until deflate stream ends or end of file */
    	do 
    	{
    		strm.avail_in = fread(in, 1, CHUNK, source);
    		if (ferror(source)) {
    			(void)inflateEnd(&strm);
    			return Z_ERRNO;
    		}
    		if (strm.avail_in == 0)
    			break;
    		strm.next_in = in;
    
    		/* run inflate() on input until output buffer not full */
    		do 
    		{
    			strm.avail_out = CHUNK;
    			strm.next_out = out;
    			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;
    			}
    
    			have = CHUNK - strm.avail_out;
    			if (fwrite(out, 1, have, dest) != have || ferror(dest)) 
    			{
    				(void)inflateEnd(&strm);
    				return Z_ERRNO;
    			}
    		} while (strm.avail_out == 0);
    
    		/* done when inflate() says it's done */
    	} while (ret != Z_STREAM_END);
    
    	/* clean up and return */
    	(void)inflateEnd(&strm);
    	return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
    }
    
    /* report a zlib or i/o error */
    void zerr(int ret)
    {
    	fputs("zpipe: ", stderr);
    	switch (ret) 
    	{
    		case Z_ERRNO:
    			if (ferror(stdin))
    				fputs("error reading stdin\n", stderr);
    			if (ferror(stdout))
    				fputs("error writing stdout\n", stderr);
    			break;
    		case Z_STREAM_ERROR:
    			fputs("invalid compression level\n", stderr);
    			break;
    		case Z_DATA_ERROR:
    			fputs("invalid or incomplete deflate data\n", stderr);
    			break;
    		case Z_MEM_ERROR:
    			fputs("out of memory\n", stderr);
    			break;
    		case Z_VERSION_ERROR:
    			fputs("zlib version mismatch!\n", stderr);
    	}
    }
    
    /* compress or decompress from stdin to stdout */
    int process(int argc, char **argv)
    {
    	int ret;
    
    	/* avoid end-of-line conversions */
    	SET_BINARY_MODE(stdin);
    	SET_BINARY_MODE(stdout);
    
    	/* do compression if no arguments */
    	if (argc == 1) 
    	{
    		ret = def(stdin, stdout, Z_DEFAULT_COMPRESSION);
    		if (ret != Z_OK)
    			zerr(ret);
    		return ret;
    	}
    
    	/* do decompression if -d specified */
    	else if (argc == 2 && strcmp(argv[1], "-d") == 0) 
    	{
    		ret = inf(stdin, stdout);
    		if (ret != Z_OK)
    			zerr(ret);
    		return ret;
    	}
    
    	/* otherwise, report usage */
    	else 
    	{
    		fputs("zpipe usage: zpipe [-d] < source > dest\n", stderr);
    		return 1;
    	}
    }
    
    int main(int argc, char **argv)
    {
    	int ret = 0;
    	int i;
    	FILE *input, *output;
    	if (argc < 4 || (strcmp(argv[1], "-l") && strcmp(argv[1], "-d"))) 
    	{
    		printf("[compress Example]: zpipe   -l 9 logo.raw battery.raw\n");
    		printf("[decompress Example]: zpipe -d xx.raw logo.raw\n");
    		return -1;
    	}
    
    	// compress
    	if(!strcmp(argv[1], "-l"))
    	{
    		char *ptemp;
    		unsigned int *pinfo;
    		int level = -1;
    		int filenum = argc - 2;
    		level = atoi(argv[2]);
    
    		input = fopen(argv[4], "rb");
    		output = fopen(argv[3], "wb");
    		ptemp = (char*)malloc(1024*1024);
    		pinfo = (unsigned int*)malloc(filenum*sizeof(int));
    		if(input < 0 || output < 0 || ptemp == NULL || pinfo == NULL)
    		{
    			fprintf(stderr, "open file and allocate temp buffer fail\n");
    			fprintf(stderr, "input = %d, output = %d, ptemp = 0x%08x, pinfo = 0x%08x\n", input, output, ptemp, pinfo);
    			ret = -1;
    			goto done;
    		}
    
    		// structre of pinfo:
    		// pinfo[0] ==> size of pinfo 
    		// pinfo[1] ==> offset of zip chunk[1]
    		// pinfo[2] ==> offset of zip chunk[2]
    		// ...
    		// pinfo[n] ==> offset of zip chunk[n]
    		// "offset" is the distance from the begining of the file, not the zip chunk
    		memset((void*)pinfo, 0, sizeof(int)*filenum);
    		// write information header to output first
    		//将文件个数写入第一位
    		if(sizeof(int)*filenum != fwrite(pinfo, 1, filenum*sizeof(int), output))
    		{
    			ret = -2;
    			goto done;
    		}
    		//获取当前指针位置,也就是文件个数写入内容的实际长度
    		pinfo[pinfo[0]+2]=ftell(output);
    		printf("pinfo[0]=%d\n", pinfo[0]);
    		printf("pinfo[pinfo[0]+2]=%d\n", pinfo[pinfo[0]+2]);
    		//开始压缩第一个文件
    		if (Z_OK != def(input, output, level)) 
    		{
    			fprintf(stderr, "compress error 111\n");
    			ret = -2;
    			goto done;
    		}
    		pinfo[0] = pinfo[0]+1;
    
    		printf("argc=%d\n", argc);
    		for (i = 5; i < argc; i++) 
    		{
    			fclose(input);
    			//循环上面过程
    			input = fopen(argv[i], "rb");
    			pinfo[pinfo[0]+2]=ftell(output);
    			if (Z_OK != def(input, output, level)) 
    			{
    				fprintf(stderr, "compress error\n");
    				ret = -2;
    				goto done;
    			}
    			pinfo[0] = pinfo[0]+1;
    		}
    
    done:
    		//将指针移动到文件末尾
    		fseek(output, 0L, SEEK_END);
    		//获取文件大小
    		pinfo[1] = ftell(output);
    		// printf("pinfo[1]=%d\n", pinfo[1]);
    		//将指针恢复到原来位置
    		fseek(output, 0L, SEEK_SET);
    		//写入数据
    		fwrite(pinfo, 1, filenum*sizeof(int), output);
    
    		for (int i = 0; i < filenum; ++i)
    		{
    			printf("pinfo[%d]=%d\n", i , pinfo[i]);
    		}
    
    		fclose(input);
    		fclose(output);
    		free(ptemp);
    		free(pinfo);
    
    		return ret;
    	}
    	// decompress
    	else
    	{
    		unsigned int temp;
    		unsigned int *pinfo;
    		char outputfilename[256];
    		//打开要解压的文件例如  logo.raw
    		input = fopen(argv[3], "rb");
    		if(input < 0)
    		{
    			printf("open file fail\n");
    			printf("input = %d\n", input);
    			ret = -1;
    			goto done2;
    		}
    		//将文件大小读取到 temp
    		fread(&temp, 1, sizeof(int), input);
    		printf("temp=%d\n", temp);
    		/*int tempLength = (temp+2)*sizeof(int);
    		printf("tempLength=%d\n", tempLength);*/
    
    		temp = temp + 1;//core
    		//申请指定大小空间
    		pinfo = malloc(temp*sizeof(int));
    		if(pinfo == NULL)
    		{
    			printf("allocate pinfo failed\n");
    			ret = -1;
    			goto done2;
    		}
    		//将文件数据读取到 pinfo
    		fread(pinfo, 1, temp*sizeof(int), input);
    
    		/*for(i=0;i
    
    		// int seekIndex = 0;
    		for(i = 0;i < temp;i++)
    		{
    			if (i == 0)
    			{
    				printf("skip pinfo 0\n");
    				continue;//core
    			}
    			printf("pinfo[%d]=%d\n", i, pinfo[i]);
    			//拼接要保存的文件名称,0_xxx.raw
    			sprintf(outputfilename, "%d_%s", i, argv[2]);
    			//打开要保存文件流
    			output = fopen(outputfilename, "wb");
    			if(output < 0)
    			{
    				printf("create output file %s fail\n", outputfilename);
    				goto done2;
    			}
    			//跳过 pinfo[i]
    			fseek(input, pinfo[i], SEEK_SET);
    			/*if (i == 0){
    				seekIndex = tempLength;
    			}
    			printf("seekIndex=%d\n", seekIndex);
    			fseek(input, seekIndex, SEEK_SET);*/
    			
    			//解压读取数据写入
    			if(Z_OK != inf(input, output))
    			{
    				printf("decompress error\n");
    				ret = -2;
    				goto done2;
    			}
    
    			fclose(output);
    			output = 0;
    			printf("decompress %s done\n", outputfilename);
    			// seekIndex += pinfo[i];
    		}
    done2:
    		fclose(input);
    		if(output) fclose(output);
    		return ret;
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311
    • 312
    • 313
    • 314
    • 315
    • 316
    • 317
    • 318
    • 319
    • 320
    • 321
    • 322
    • 323
    • 324
    • 325
    • 326
    • 327
    • 328
    • 329
    • 330
    • 331
    • 332
    • 333
    • 334
    • 335
    • 336
    • 337
    • 338
    • 339
    • 340
    • 341
    • 342
    • 343
    • 344
    • 345
    • 346
    • 347
    • 348
    • 349
    • 350
    • 351
    • 352
    • 353
    • 354
    • 355
    • 356
    • 357
    • 358
    • 359
    • 360
    • 361
    • 362
    • 363
    • 364
    • 365
    • 366
    • 367
    • 368
    • 369
    • 370
    • 371
    • 372
    • 373
    • 374
    • 375
    • 376
    • 377
    • 378
    • 379
    • 380
    • 381
    • 382
    • 383
    • 384
    • 385
    • 386
    • 387
    • 388
    • 389

    三、编译指令

    gcc -o zpipe zpipe.c -lz

    zpipe下载

    四、解压 rawx 文件

    使用方法

    [compress Example]: zpipe -l 9 logo.raw battery.raw
    [decompress Example]: zpipe -d xx.raw logo.raw

  • 相关阅读:
    巨控GRM530,GRM230远程模块教你如何实现手机(电脑)无线远程监控西门子S7-smart200 plc
    国际计费系统基于Sharding-Proxy大数据迁移方案实践
    系列十二、强引用、软引用、弱引用、虚引用分别是什么?
    TCP 小结
    杰理之AT 包格式【篇】
    Comfyui|AnimateDiff生成动画基础使用方法
    VAE模型(详细推导+实例代码)
    OpenHarmony网络协议通信—kcp
    深入解析Go非类型安全指针:技术全解与最佳实践
    【案例】【技术难点(已解决)】vue 线上项目访问本地资源 访问不到、跨域等问题的解决方法
  • 原文地址:https://blog.csdn.net/u012932409/article/details/133744186