酷派CPB升级文件封包解包

本文介绍了一款专门针对酷派CPB 1.7版本的解包和打包工具,包括如何使用该工具进行文件的操作,并提供了详细的源代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

      此前入手了部酷派8730L,无奈搜遍整个互联网寻求ROOT的方法以及用了各种ROOT工具均以失败告终。于是决定研究下酷派的CPB升级文件:4.3.066.P3.140417.8730L.CPB。以为解包出来改改某个文件再封包,然后刷机可以解决ROOT的问题(后来事实证明太天真啦,CDS这个升级工具根本就没法用,让我机器变砖头的机会都不给),于是下载个cpb解包封包工具试下,没想到又失败了。没办法只能参考找到的部分cpb文件格式资料,自己写解包封包工具。OD动态调试CDS升级工具(版本:V4.29_140116_01),发现cpb文件验证过程在dChkData.dll中完成,研究一番,写了个自己的CPB解包封包工具,代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <direct.h>
#include <stddef.h>

typedef char int8 ;
typedef unsigned char uint8 ;
typedef short int16 ;
typedef unsigned short uint16 ;
typedef int int32 ;
typedef unsigned int uint32 ;
typedef __int64 int64 ;
typedef unsigned __int64 uint64 ;

typedef struct tagCPBHEADER
{
	char cp_magic[2] ;		//'CP'
	uint8 cp_version[2] ; 	//CPB文件版本
	uint16 correct[6] ;		//12字节校正用 
	uint8 unknown[32] ;		//未知32字节
	char model[32] ;		//适用的手机型号,如"8730L" 
	char hardVersion[16] ;	//适用的硬件版本号,如"P3"
	char version[64] ;		//适用的版本号,如"4.3.066.P3.140417.8730L"
	char romFrom[256] ;		//
	uint32 imgHdrEndPos ; 	//Image Header停止的位置,这样就能确定Image Header大小
	uint8 reverse[128] ;  	//保留
	uint32 checkSum ;		//校验和(CRC16) 
}CPBHEADER, *LPCPBHEADER ;

typedef struct tagIMAGEHEADER
{
    char fileName[64] ;
    uint32 imageOffset ;
    uint32 imageSize ;
    uint32 checkSum ;//CRC16
}IMAGEHEADER, *LPIMAGEHEADER;

const uint16 CRC16Tab[256] =
{
	0x0000L, 0x1021L, 0x2042L, 0x3063L,
	0x4084L, 0x50a5L, 0x60c6L, 0x70e7L,
	0x8108L, 0x9129L, 0xa14aL, 0xb16bL,
	0xc18cL, 0xd1adL, 0xe1ceL, 0xf1efL,
	0x1231L, 0x0210L, 0x3273L, 0x2252L,
	0x52b5L, 0x4294L, 0x72f7L, 0x62d6L,
	0x9339L, 0x8318L, 0xb37bL, 0xa35aL,
	0xd3bdL, 0xc39cL, 0xf3ffL, 0xe3deL,
	0x2462L, 0x3443L, 0x0420L, 0x1401L,
	0x64e6L, 0x74c7L, 0x44a4L, 0x5485L,
	0xa56aL, 0xb54bL, 0x8528L, 0x9509L,
	0xe5eeL, 0xf5cfL, 0xc5acL, 0xd58dL,
	0x3653L, 0x2672L, 0x1611L, 0x0630L,
	0x76d7L, 0x66f6L, 0x5695L, 0x46b4L,
	0xb75bL, 0xa77aL, 0x9719L, 0x8738L,
	0xf7dfL, 0xe7feL, 0xd79dL, 0xc7bcL,
	0x48c4L, 0x58e5L, 0x6886L, 0x78a7L,
	0x0840L, 0x1861L, 0x2802L, 0x3823L,
	0xc9ccL, 0xd9edL, 0xe98eL, 0xf9afL,
	0x8948L, 0x9969L, 0xa90aL, 0xb92bL,
	0x5af5L, 0x4ad4L, 0x7ab7L, 0x6a96L,
	0x1a71L, 0x0a50L, 0x3a33L, 0x2a12L,
	0xdbfdL, 0xcbdcL, 0xfbbfL, 0xeb9eL,
	0x9b79L, 0x8b58L, 0xbb3bL, 0xab1aL,
	0x6ca6L, 0x7c87L, 0x4ce4L, 0x5cc5L,
	0x2c22L, 0x3c03L, 0x0c60L, 0x1c41L,
	0xedaeL, 0xfd8fL, 0xcdecL, 0xddcdL,
	0xad2aL, 0xbd0bL, 0x8d68L, 0x9d49L,
	0x7e97L, 0x6eb6L, 0x5ed5L, 0x4ef4L,
	0x3e13L, 0x2e32L, 0x1e51L, 0x0e70L,
	0xff9fL, 0xefbeL, 0xdfddL, 0xcffcL,
	0xbf1bL, 0xaf3aL, 0x9f59L, 0x8f78L,
	0x9188L, 0x81a9L, 0xb1caL, 0xa1ebL,
	0xd10cL, 0xc12dL, 0xf14eL, 0xe16fL,
	0x1080L, 0x00a1L, 0x30c2L, 0x20e3L,
	0x5004L, 0x4025L, 0x7046L, 0x6067L,
	0x83b9L, 0x9398L, 0xa3fbL, 0xb3daL,
	0xc33dL, 0xd31cL, 0xe37fL, 0xf35eL,
	0x02b1L, 0x1290L, 0x22f3L, 0x32d2L,
	0x4235L, 0x5214L, 0x6277L, 0x7256L,
	0xb5eaL, 0xa5cbL, 0x95a8L, 0x8589L,
	0xf56eL, 0xe54fL, 0xd52cL, 0xc50dL,
	0x34e2L, 0x24c3L, 0x14a0L, 0x0481L,
	0x7466L, 0x6447L, 0x5424L, 0x4405L,
	0xa7dbL, 0xb7faL, 0x8799L, 0x97b8L,
	0xe75fL, 0xf77eL, 0xc71dL, 0xd73cL,
	0x26d3L, 0x36f2L, 0x0691L, 0x16b0L,
	0x6657L, 0x7676L, 0x4615L, 0x5634L,
	0xd94cL, 0xc96dL, 0xf90eL, 0xe92fL,
	0x99c8L, 0x89e9L, 0xb98aL, 0xa9abL,
	0x5844L, 0x4865L, 0x7806L, 0x6827L,
	0x18c0L, 0x08e1L, 0x3882L, 0x28a3L,
	0xcb7dL, 0xdb5cL, 0xeb3fL, 0xfb1eL,
	0x8bf9L, 0x9bd8L, 0xabbbL, 0xbb9aL,
	0x4a75L, 0x5a54L, 0x6a37L, 0x7a16L,
	0x0af1L, 0x1ad0L, 0x2ab3L, 0x3a92L,
	0xfd2eL, 0xed0fL, 0xdd6cL, 0xcd4dL,
	0xbdaaL, 0xad8bL, 0x9de8L, 0x8dc9L,
	0x7c26L, 0x6c07L, 0x5c64L, 0x4c45L,
	0x3ca2L, 0x2c83L, 0x1ce0L, 0x0cc1L,
	0xef1fL, 0xff3eL, 0xcf5dL, 0xdf7cL,
	0xaf9bL, 0xbfbaL, 0x8fd9L, 0x9ff8L,
	0x6e17L, 0x7e36L, 0x4e55L, 0x5e74L,
	0x2e93L, 0x3eb2L, 0x0ed1L, 0x1ef0L
};

uint32 CRC16(const uint8 *pData, uint32 nSize, uint32 uiCrc)
{
    uint32 i;

    for (i=0; i<nSize; i++)
        uiCrc = (uiCrc << 8) ^ (uint16)CRC16Tab[(uint8)(uiCrc >> 8) ^ pData[i]];
    return uiCrc ;
}

int32 MkdirRecursive( char* path )
{
	char *p, ch;
	if( access( path, 0 ) == 0 )
		return 0;
	for( p=path; *p; p++ )
	{
		if( p>path && ((*p == '/') || (*p == '\\')) )
		{
			ch = *p ;
			*p = 0;
			if( access( path, 0 ) != 0 )
			{
				if( mkdir( path ) != 0 )
					return -1;
			}
			*p = ch ;
		}
	}
	return mkdir( path );
}

void usage(void)
{
	printf("本工具限用于酷派CPB1.7版本。即cpb文件头4字节为\"CP\\x01\\x07\"。\n") ;
    printf("usage: cpbtool.exe\n"
    	"  [-l <CPB文件> <列表文件>]\n\t#列出CPB的所有文件为列表文件。\n"
    	"  [-u <CPB文件> <路径>]\n\t#解压CPB文件到指定目录。\n"
    	"  [-p <型号> <硬件版本> <版本号> <路径> <列表文件> <CPB文件>]\n\t#打包指定目录下的文件为CPB包。\n"
	) ;
	printf("Ex: cpbtool.exe -l ex.cpb list.txt\n") ;
	printf("    cpbtool.exe -u ex.cpb .\\8730L\n") ;
	printf("    cpbtool.exe -p 8730L P3 4.3.066.P3.140417.8730L .\\8730L list.txt new.cpb\n") ;
}

void PrintCpbHeader(LPCPBHEADER pHdr)
{
	char buf[512] ;
	printf("CPB文件版本:%d.%d\n", pHdr->cp_version[0], pHdr->cp_version[1]) ;
	strncpy(buf, pHdr->model, sizeof(buf)) ;
	printf("适用的手机型号:%s\n", buf) ;
	strncpy(buf, pHdr->hardVersion, sizeof(buf)) ;
	printf("适用的硬件版本号:%s\n", buf) ;
	strncpy(buf, pHdr->version, sizeof(buf)) ;
	printf("适用的版本号:%s\n", buf) ;
	printf("映像文件头大小:%u,每个76字节,共%u个。\n", 
		pHdr->imgHdrEndPos-sizeof(CPBHEADER), (pHdr->imgHdrEndPos-sizeof(CPBHEADER)) / sizeof(IMAGEHEADER)) ;
	printf("校验和:0x%08X\n\n", pHdr->checkSum) ;
}

void CreateListFile(const char *lpszCpb, const char *lpszList)
{
	FILE *fcpb = NULL ;
	FILE *flst = NULL ;
	CPBHEADER cpbHdr ;
	LPIMAGEHEADER pImgHdr = NULL ;
	size_t sz ;
	uint32 nImgSize, nImgCount, i ;
	
	fcpb = fopen(lpszCpb, "rb") ;
	if (fcpb == NULL)
	{
		printf("打开文件“%s”失败!\n", lpszCpb) ;
		return 0 ;
	}
	sz = fread(&cpbHdr, sizeof(cpbHdr), 1, fcpb);
	if(sz != 1 || cpbHdr.cp_magic[0] != 'C' || cpbHdr.cp_magic[1] != 'P' ||
		cpbHdr.imgHdrEndPos < sizeof(cpbHdr))
	{
		fclose(fcpb) ;
		printf("不是有效的CPB文件!\n") ;
		return 0;
	}
	if(cpbHdr.cp_version[0] != 0x01 || cpbHdr.cp_version[1] != 0x07)
	{
		printf("本工具限用于酷派CPB1.7版本。即cpb文件头4字节为\"CP\\x01\\x07\"。\n") ;
		return ;
	}
	PrintCpbHeader(&cpbHdr) ;
	nImgSize = cpbHdr.imgHdrEndPos - sizeof(CPBHEADER) ;
	nImgCount = (cpbHdr.imgHdrEndPos - sizeof(CPBHEADER)) / sizeof(IMAGEHEADER) ;
	pImgHdr = (LPIMAGEHEADER)malloc(nImgSize) ;
	if(pImgHdr == NULL)
	{
		fclose(fcpb) ;
		printf("分配内存%u字节失败,可能是文件不合法!\n", nImgSize) ;
		return 0 ;
	}
	sz = fread(pImgHdr, nImgSize, 1, fcpb) ;
	if(sz != 1)
	{
		free(pImgHdr) ;
		fclose(fcpb) ;
		printf("不是有效的CPB文件!\n") ;
		return 0 ;
	}
	flst = fopen(lpszList, "w") ;
	if(flst != NULL)
	{
		for(i=0; i<nImgCount; i++)
			fprintf(flst, "%s\n", pImgHdr[i].fileName) ;
		fclose(flst) ;
		printf("列表文件‘%s’创建成功!\n", lpszList) ;
	}
	else
		printf("列表文件‘%s’创建失败!\n", lpszList) ;
	free(pImgHdr) ;
	fclose(fcpb) ;
	return 0 ;
}

void PrintfImageHeader(LPIMAGEHEADER pImgHdr)
{
	char buf[128] ;
	strncpy(buf, pImgHdr->fileName, sizeof(buf)) ;
	printf("文件名:%s\n", buf) ;
	printf("偏移:0x%08X\n", pImgHdr->imageOffset) ;
	printf("大小:0x%08X(%u)\n", pImgHdr->imageSize, pImgHdr->imageSize) ;
	printf("校验和:0x%08X\n", pImgHdr->checkSum) ;
}

void ImageHeaderCorrectPosSize(LPIMAGEHEADER pImgHdr, int32 idx, uint32 uiCorrect)
{
	uint32 iPos, nSize, iTemp ;
	uint8 bt1, bt2, bt3, bt4 ;
	bt1 = (uint8)idx + (uint8)uiCorrect ;
	bt2 = (uint8)idx + (uint8)(uiCorrect >> 8) ;
	bt3 = (uint8)idx + (uint8)(uiCorrect >> 16) ;
	bt4 = (uint8)idx + (uint8)(uiCorrect >> 24) ;
	iPos = pImgHdr->imageOffset ;
	nSize = pImgHdr->imageSize ;
	iPos = (uint8)(bt3 ^ iPos) | 
		(uint16)((uint8)(bt4 ^ (uint8)(iPos >> 8)) << 8) | 
		(((uint8)(bt1 ^ ((uint32)iPos >> 16)) | 
		(uint16)((uint8)(bt2 ^ (uint8)(iPos >> 24)) << 8)) << 16);
	iTemp = (uint8)(bt3 ^ nSize);
	nSize = iTemp | (uint16)((uint8)(bt4 ^ (uint8)(nSize >> 8)) << 8) | 
		(((uint8)(bt1 ^ ((uint32)nSize >> 16)) | 
		(uint16)((uint8)(bt2 ^ (uint8)(nSize >> 24)) << 8)) << 16);
	pImgHdr->imageOffset = iPos ;
	pImgHdr->imageSize = nSize ;
}

void DumpFile(FILE *fcpb, const char *lpszPath, LPIMAGEHEADER pImgHdrs, uint32 nImgCount)
{
	FILE *fImg ;
	char szFile[512] ;
	uint8 *pBuf ;
	uint32 i, iBufSize, nLen, uiCrc = 0;
	if(pImgHdrs == NULL) return ;
	iBufSize = 1024 * 1024 ; //1MiB
	pBuf = (uint8 *)malloc(iBufSize) ;
	if(pBuf == NULL)
	{
		printf("DumpFile 分配内存失败!\n") ;
		return ;
	}
	for(i=0; i<nImgCount; i++)
	{
		PrintfImageHeader(&pImgHdrs[i]) ;
		if(pImgHdrs[i].imageSize == 0) continue ;
		if(fseek(fcpb, pImgHdrs[i].imageOffset, SEEK_SET) != 0)
		{
			printf("生成文件“%s”失败!原CPB文件无法定位到:0x%08X\n\n", 
				pImgHdrs[i].fileName, pImgHdrs[i].imageOffset) ;
			continue ;
		}
		sprintf(szFile, "%s%s", lpszPath, pImgHdrs[i].fileName) ;
		fImg = fopen(szFile, "wb") ;
		if(fImg == NULL)
		{
			printf("创建文件‘%s’失败!\n", szFile) ;
			continue ;
		}
		for(nLen=0, uiCrc=0; (nLen+iBufSize)<=pImgHdrs[i].imageSize; nLen+=iBufSize)
		{
			if(fread(pBuf, iBufSize, 1, fcpb) != 1)
			{
				printf("生成文件“%s”失败!原CPB文件有误!\n\n", pImgHdrs[i].fileName) ;
				break ;
			}
			uiCrc = CRC16(pBuf, iBufSize, uiCrc) ;
			fwrite(pBuf, iBufSize, 1, fImg) ;
		}
		nLen = pImgHdrs[i].imageSize - nLen ;
		if(nLen > 0)
		{
			if(fread(pBuf, nLen, 1, fcpb) == 1)
			{
				uiCrc = CRC16(pBuf, nLen, uiCrc) ;
				fwrite(pBuf, nLen, 1, fImg) ;
			}
			else
				printf("生成文件“%s”失败!原CPB文件有误!\n\n", pImgHdrs[i].fileName) ;
		}
		fclose(fImg) ;
		if(uiCrc != pImgHdrs[i].checkSum)
			printf("校验失败!生成的文件“%s”非法!原CPB文件有误!\n\n", pImgHdrs[i].fileName) ;
		else
			printf("文件“%s”创建成功!\n\n", pImgHdrs[i].fileName) ;
	}
	free(pBuf) ;
}

void UnpackCpb(const char *lpszCpb, const char *lpszPath)
{
	FILE *fcpb = NULL;
	CPBHEADER cpbHdr ;
	LPIMAGEHEADER pImgHdr = NULL ;
	size_t sz ;
	uint32 nImgSize, nImgCount, i, uiCrc, uiCorrect ;
	uint64 uiVal64 ;
	char szPath[264] ;
	
	if(lpszPath == NULL || lpszPath[0]=='\0')
	{
		printf("无效目录!\n") ;
		return ;
	}
	strncpy(szPath, lpszPath, sizeof(szPath)) ;
	if(MkdirRecursive(szPath) != 0)
	{
		printf("创建目录‘%s’失败!\n", lpszPath) ;
		return ;
	}
	sz = strlen(szPath) ;
	if(szPath[sz-1] != '/' && szPath[sz-1] != '\\')
	{
		szPath[sz] = '\\' ;
		szPath[sz+1] = '\0' ;
	}
	
	fcpb = fopen(lpszCpb, "rb") ;
	if (fcpb == NULL)
	{
		printf("打开文件“%s”失败!\n", lpszCpb) ;
		return ;
	}
	sz = fread(&cpbHdr, sizeof(cpbHdr), 1, fcpb);
	if(sz != 1 || cpbHdr.cp_magic[0] != 'C' || cpbHdr.cp_magic[1] != 'P' ||
		cpbHdr.imgHdrEndPos < sizeof(cpbHdr))
	{
		fclose(fcpb) ;
		printf("不是有效的CPB文件!\n") ;
		return ;
	}
	if(cpbHdr.cp_version[0] != 0x01 || cpbHdr.cp_version[1] != 0x07)
	{
		printf("本工具限用于酷派CPB1.7版本。即cpb文件头4字节为\"CP\\x01\\x07\"。\n") ;
		return ;
	}
	uiCorrect = 0 ;
	for(i=0; i<6; i++)
		uiCorrect += cpbHdr.correct[i] ;
	uiVal64 = (uint64)0x66666667 * uiCorrect ;
	uiCorrect = (uint32)((int32)(uiVal64 >> 32)) >> 1 ;
	uiCorrect = (uint16)((uiCorrect >> 31) + uiCorrect) ;
	uiCorrect = (uiCorrect-cpbHdr.correct[3]) | ((uiCorrect-cpbHdr.correct[4]) << 16) ;
	uiCrc = CRC16((uint8 *)&cpbHdr, sizeof(cpbHdr)-4, 0) ;
	PrintCpbHeader(&cpbHdr) ;
	nImgSize = cpbHdr.imgHdrEndPos - sizeof(CPBHEADER) ;
	nImgCount = (cpbHdr.imgHdrEndPos - sizeof(CPBHEADER)) / sizeof(IMAGEHEADER) ;
	pImgHdr = (LPIMAGEHEADER)malloc(nImgSize) ;
	if(pImgHdr == NULL)
	{
		fclose(fcpb) ;
		printf("分配内存%u字节失败,可能是文件不合法!\n", nImgSize) ;
		return ;
	}
	sz = fread(pImgHdr, nImgSize, 1, fcpb) ;
	if(sz != 1)
	{
		free(pImgHdr) ;
		fclose(fcpb) ;
		printf("不是有效的CPB文件!\n") ;
		return ;
	}
	for(i=0; i<nImgCount; i++)
	{
		ImageHeaderCorrectPosSize(&pImgHdr[i], i, uiCorrect);
		uiCrc = CRC16((uint8 *)&pImgHdr[i], sizeof(IMAGEHEADER), uiCrc) ;
	}
	uiCrc += cpbHdr.cp_version[1] ;
	if(uiCrc != cpbHdr.checkSum)
	{
		free(pImgHdr) ;
		fclose(fcpb) ;
		printf("校验失败!期望的CPB校验值:0x%.8X,实际值:0x%.8X\n",
			cpbHdr.checkSum, uiCrc) ;
		return ;
	}
	DumpFile(fcpb, szPath, pImgHdr, nImgCount) ;
	free(pImgHdr) ;
	fclose(fcpb) ;
	return ;
}

void TrimCRLF(char *str)
{
	int32 nLen ;
	nLen = strlen(str) - 1 ;
	for(; nLen>=0; nLen--)
	{
		if(str[nLen]=='\r' || str[nLen]=='\n')
			str[nLen] = '\0' ;
		else
			break ;
	}
}

void InitCpbHeader(LPCPBHEADER pCpbHdr, const char *lpszModel, const char *lpszHardVer,
	const char *lpszVersion, const char *lpszFrom)
{
	uint16 arrCorrect[6] = {0x005C, 0x0836, 0x0828, 0x083A, 0x0809, 0x0825} ;
	uint8 unknown[33] = "\x55\x35\x25\x27\x28\x59\x2D\x11\x32\x2D\x24\x3D\x5B\x2B\x3F\x11"
						"\x0C\x16\x07\x01\x11\x16\x10\x03\x06\x13\x03\x1C\x01\x06\x00\x00" ;
	memset(pCpbHdr, 0, sizeof(CPBHEADER)) ;
	pCpbHdr->cp_magic[0] = 'C' ;
	pCpbHdr->cp_magic[1] = 'P' ;
	pCpbHdr->cp_version[0] = 0x01 ;
	pCpbHdr->cp_version[1] = 0x07 ;
	memcpy(pCpbHdr->correct, arrCorrect, sizeof(arrCorrect)) ;
	memcpy(pCpbHdr->unknown, unknown, sizeof(pCpbHdr->unknown)) ;
	strncpy(pCpbHdr->model, lpszModel, sizeof(pCpbHdr->model)) ;
	strncpy(pCpbHdr->hardVersion, lpszHardVer, sizeof(pCpbHdr->hardVersion)) ;
	strncpy(pCpbHdr->version, lpszVersion, sizeof(pCpbHdr->version)) ;
	strncpy(pCpbHdr->romFrom, lpszFrom, sizeof(pCpbHdr->romFrom)) ;
}

uint32 WriteImageHeaders(FILE *fcpb, LPIMAGEHEADER pImgHdrs, int32 nCount, uint32 uiCorrect, uint32 uiCrc)
{
	uint32 uiOffset, uiSize ;
	int32 i ;
	for(i=0; i<nCount; i++)
	{
		uiOffset = pImgHdrs[i].imageOffset ;
		uiSize = pImgHdrs[i].imageSize ;
		uiCrc = CRC16(&pImgHdrs[i], sizeof(IMAGEHEADER), uiCrc) ;
		ImageHeaderCorrectPosSize(&pImgHdrs[i], i, uiCorrect) ;
		fwrite(&pImgHdrs[i], sizeof(IMAGEHEADER), 1, fcpb) ;
		pImgHdrs[i].imageOffset = uiOffset ;
		pImgHdrs[i].imageSize = uiSize ;
	}
	return uiCrc ;
}

void WriteImages(FILE *fcpb, FILE *fImgs[], LPIMAGEHEADER pImgHdrs, int32 nCount)
{
	int32 i ;
	uint32 iBufSize, nLen, uiCrc ;
	uint8 *pBuf ;
	iBufSize = 1024 * 1024 ; //1MiB
	pBuf = (uint8 *)malloc(iBufSize) ;
	if(pBuf == NULL)
	{
		printf("写入映像文件时,申请1MiB内存失败!\n") ;
		exit(1) ;
		return ;
	}
	for(i=0; i<nCount; i++)
	{
		printf("写入‘%s’文件...\n", pImgHdrs[i].fileName) ;
		uiCrc = 0 ;
		for(nLen=0; (nLen+iBufSize)<=pImgHdrs[i].imageSize; nLen+=iBufSize)
		{
			fread(pBuf, iBufSize, 1, fImgs[i]) ;
			uiCrc = CRC16(pBuf, iBufSize, uiCrc) ;
			fwrite(pBuf, iBufSize, 1, fcpb) ;
		}
		nLen = pImgHdrs[i].imageSize - nLen ;
		if(nLen > 0)
		{
			fread(pBuf, nLen, 1, fImgs[i]) ;
			uiCrc = CRC16(pBuf, nLen, uiCrc) ;
			fwrite(pBuf, nLen, 1, fcpb) ;
		}
		pImgHdrs[i].checkSum = uiCrc ;
	}
	free(pBuf) ;
}

void PackCpb(LPCPBHEADER pCpbHdr, const char *lpszPath, const char *lpszList, const char *lpszCpb)
{
#define MAX_IMG	500
	FILE *flst = NULL ;
	FILE *fcpb = NULL ;
	FILE *fImgs[MAX_IMG] ;
	char szPath[260], szFile[512] ;
	LPIMAGEHEADER pImgHdr = NULL ;
	int32 i, nCount ;
	uint32 uiCrc, uiCorrect, uiSize ;
	uint64 uiVal64 ;
	
	if(lpszPath == NULL || lpszPath[0]=='\0' || access(lpszPath, 0) != 0)
	{
		printf("‘%s’无效目录!\n", lpszPath) ;
		return ;
	}
	strncpy(szPath, lpszPath, sizeof(szPath)) ;
	uiSize = strlen(szPath) ;
	if(szPath[uiSize-1] != '/' && szPath[uiSize-1] != '\\')
	{
		szPath[uiSize] = '\\' ;
		szPath[uiSize+1] = '\0' ;
	}
	//在此之前确保已经调用InitCpbHeader函数 
	uiCorrect = 0 ;
	for(i=0; i<6; i++)
		uiCorrect += pCpbHdr->correct[i] ;
	uiVal64 = (uint64)0x66666667 * uiCorrect ;
	uiCorrect = (uint32)((int32)(uiVal64 >> 32)) >> 1 ;
	uiCorrect = (uint16)((uiCorrect >> 31) + uiCorrect) ;
	uiCorrect = (uiCorrect-pCpbHdr->correct[3]) | ((uiCorrect-pCpbHdr->correct[4]) << 16) ;
	
	if(access( lpszPath, 0 ) != 0)
	{
		printf("路径‘%s’无法访问!\n", lpszPath) ;
		return ;
	}
	flst = fopen(lpszList, "r") ;
	if(flst == NULL)
	{
		printf("列表文件‘%s’打开失败!\n", lpszList) ;
		return ;
	}
	fcpb = fopen(lpszCpb, "wb") ;
	if(fcpb == NULL)
	{
		fclose(flst) ;
		printf("创建文件‘%s’失败!\n", lpszCpb) ;
		return ;
	}
	pImgHdr = malloc(sizeof(IMAGEHEADER) * MAX_IMG) ;
	if(pImgHdr == NULL)
	{
		fclose(flst) ;
		fclose(fcpb) ;
		printf("申请映像头内存失败!\n") ;
		return ;
	}
	
	for(nCount=0; nCount<MAX_IMG && fgets(pImgHdr[nCount].fileName, sizeof(pImgHdr[nCount].fileName)-1, flst); )
	{
		TrimCRLF(pImgHdr[nCount].fileName) ;
		sprintf(szFile, "%s%s", szPath, pImgHdr[nCount].fileName) ;
		fImgs[nCount] = fopen(szFile, "rb") ;
		if(fImgs[nCount])
		{
			if(fseek(fImgs[nCount], 0, SEEK_END) != 0)
			{
				printf("文件‘%s’定位失败!\n", szFile) ;
				continue ;
			}
			pImgHdr[nCount].imageOffset += sizeof(IMAGEHEADER) ;
			pImgHdr[nCount].imageSize = ftell(fImgs[nCount]) ;
			if((int32)pImgHdr[nCount].imageSize == -1)
			{
				printf("获取文件‘%s’大小失败!\n", szFile) ;
				continue ;
			}
			fseek(fImgs[nCount], 0, SEEK_SET) ;
			nCount++ ;
		}
		else printf("文件‘%s’打开失败!\n", szFile) ;
	}
	pCpbHdr->imgHdrEndPos = sizeof(CPBHEADER) + nCount * sizeof(IMAGEHEADER) ;
	uiCrc = CRC16((uint8 *)pCpbHdr, sizeof(CPBHEADER)-4, 0) ;
	fwrite(pCpbHdr, sizeof(CPBHEADER), 1, fcpb) ; //写入头
	fwrite(pImgHdr, sizeof(IMAGEHEADER)*nCount, 1, fcpb) ; //写入映像文件头 
	WriteImages(fcpb, fImgs, pImgHdr, nCount) ;
	fseek(fcpb, sizeof(CPBHEADER), SEEK_SET) ;
	uiCrc = WriteImageHeaders(fcpb, pImgHdr, nCount, uiCorrect, uiCrc) ;
	uiCrc += pCpbHdr->cp_version[1] ;
	fseek(fcpb, offsetof(CPBHEADER, checkSum), SEEK_SET) ;
	fwrite(&uiCrc, 4, 1, fcpb) ;
	for(i=0; i<nCount; i++)
		fclose(fImgs[i]) ;
	free(pImgHdr) ;
	fclose(flst) ;
	fclose(fcpb) ;
}

int main(int argc, char *argv[])
{
	char *lpszCpb = NULL ;
	char *lpszPath = NULL ;
	char *lpszList = NULL ;
	char *lpszModel = NULL ;
	char *lpszHardVer = NULL ;
	char *lpszVersion = NULL ;
	CPBHEADER cpbHdr ;
	
	if(argc < 4)
	{
		usage() ;
		return 0 ;
	}
	switch(argv[1][1])
	{
	case 'l':
	case 'L':
		lpszCpb = argv[2] ;
		lpszList = argv[3] ;
		CreateListFile(lpszCpb, lpszList) ;
		break ;
		
	case 'u':
	case 'U':
		lpszCpb = argv[2] ;
		lpszPath = argv[3] ;
		UnpackCpb(lpszCpb, lpszPath) ;
		break ;
		
	case 'p':
	case 'P':
		if(argc < 8)
		{
			usage() ;
			return 0 ;
		}
		lpszModel = argv[2] ;
		lpszHardVer = argv[3] ;
		lpszVersion = argv[4] ;
		lpszPath = argv[5] ;
		lpszList = argv[6] ;
		lpszCpb = argv[7] ;
		InitCpbHeader(&cpbHdr, lpszModel, lpszHardVer, lpszVersion, "D:\\image") ;
		PackCpb(&cpbHdr, lpszPath, lpszList, lpszCpb) ;
		break ;
		
	default:
		usage() ;
		return 0 ;
	}
	return 0 ;
}



完整的下载地址:这里

转载于:https://my.oschina.net/osbin/blog/266431

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值