C语言操作二进制文件

2 篇文章 1 订阅
有这样一种需求,在做OTA升级文件时需要根据本地编译生成的bin文件计算出一个头信息加再本地编译生成的bin文件头部组成一个新的bin文件放在服务器上,下面c语言是我写的一个例子。
// filename: make_ota_bin.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#define HRADER_FLAG 0xaa55aa55
#define TAIL_FLAG   0x55aa55aa

#define FILE_TYPE   ".bin"
typedef struct
{
    unsigned int header_flag;//0xaa55aa55
    unsigned int sw_version;//sofrware version
    unsigned int bin_len;
    unsigned int bin_sum;
    unsigned int head_sum;//header_flag + sw_version + bin_len + bin_sum
    unsigned int tail_flag;//0x55aa55aa
}BOOTLOADER_UPDATE_FILE_HDR_S;

int main(int argc,char* argv[])
{

	if(argc<3 || argc>4)
	{
		printf("参数个数错误 例子:bin文件名 主版本号.子版本号 [生成ota文件名字](可选)\n");
		printf("./make_ota_bin.o xxx.bin 1.0 [ota.bin]\n");
		return 0;
	}
	char* file_name = argv[1];
	if( strcmp(file_name+strlen(file_name)-strlen(FILE_TYPE),FILE_TYPE) !=0)
	{	
		printf("bin文件名后缀错误\n");
		return 0;
	}
	
	
	char* main_ver=NULL;char* sub_ver =NULL;
	main_ver = argv[2];
	sub_ver = strchr(argv[2],'.');	
	char * create_file_name =NULL;
	if(argc ==4)
	{
		create_file_name = argv[3];
		if( strcmp(create_file_name+strlen(create_file_name)-strlen(FILE_TYPE),FILE_TYPE) !=0)
		{	
			printf("生成ota文件名字后缀错误\n");
			return 0;
		}	
	}
	
	BOOTLOADER_UPDATE_FILE_HDR_S ota_header={0};
	ota_header.header_flag = HRADER_FLAG;
	ota_header.tail_flag   = TAIL_FLAG;
	
	if(sub_ver == NULL)
	{
		printf("sw_version param err --> main_ver.sub_ver\n");
		return 0;
	}
	sub_ver++;
	ota_header.sw_version = (atol(main_ver)<<16) |atol(sub_ver);
	
	printf("sw_version %02d.%02d\n",(ota_header.sw_version&0xFFFF0000)>>16,(ota_header.sw_version&0xFFFF));
	
	printf("bin name :%s \n",file_name);
	FILE *fp_bin = fopen(file_name,"rb");	
	FILE * fp_out=NULL;
	if(fp_bin == NULL)
	{
		printf("open file err\n");
		return 0;
	}
	if(fseek(fp_bin,0,SEEK_END) != 0)
	{
		printf("fseek file err\n");
		goto exit;
	}
	ota_header.bin_len = ftell(fp_bin);
	printf("bin size :%d-hex(%x)\n",ota_header.bin_len,ota_header.bin_len);
	int retry;
	
	retry =0 ;
lp_retry:
	fseek(fp_bin,0,SEEK_SET);
	unsigned char dat;
	int i=0;ota_header.head_sum=0; int ret=0;
	while( (ret = fread(&dat,1,1,fp_bin)) !=0)
	{
		if(ret == 1)
		{
			i++;
			ota_header.bin_sum += dat;
			retry = 0;
		}
		else 
		{
			printf("fread err retry %d\n",retry);
			retry++;
			if(retry <10)
				goto lp_retry;
			else 
				goto exit;
		}
	}
    if(i!=ota_header.bin_len)
	{
		printf("read err\n");
		goto exit;
	}
	printf("read done\n");
    ota_header.head_sum = ota_header.header_flag + ota_header.sw_version + ota_header.bin_len + ota_header.bin_sum;
	/*
	printf("#########bin header info#######\n");
	printf("header_flag : %X\n",ota_header.header_flag);
	printf("sw_version :  %X\n",ota_header.sw_version);
	printf("bin_len :     %X\n",ota_header.bin_len);
	printf("bin_sum :     %X\n",ota_header.bin_sum);
	printf("head_sum :    %X\n",ota_header.head_sum);
	printf("tail_flag :   %X\n",ota_header.tail_flag);
	printf("##############################\n");
	printf("%d\n",sizeof(BOOTLOADER_UPDATE_FILE_HDR_S));
	*/
	char *ota_file_name=NULL;
	if(argc == 3)
		ota_file_name = calloc(strlen("ota_")+strlen(file_name)+1,sizeof(char));
	else if(argc == 4 && create_file_name!= NULL)
		ota_file_name = calloc(strlen(create_file_name)+1,sizeof(char));
	
	if(ota_file_name == NULL)
	{
		printf("ota_file_name zalloc fail\r\n");
		goto exit;
	}
	if(argc == 3)
	{
		sprintf(ota_file_name,"ota_%s",file_name);
	}
	else if(argc ==4)
	{
		memcpy(ota_file_name,create_file_name,strlen(create_file_name));
	}
	printf("create ota name: %s\n",ota_file_name);
	
	fp_out = fopen(ota_file_name,"wb+");
	if(fp_out == NULL)
	{
		printf("无法打开 %s\n",ota_file_name);
		goto exit;
	}
	
	retry = 0;ret = 0;
lp1_retry:
	fseek(fp_out,0,SEEK_SET);
	if( (ret = fwrite(&ota_header,sizeof(BOOTLOADER_UPDATE_FILE_HDR_S),1,fp_out)) != 1 )
	{
		printf("fwrite ota header retry %d\n",retry);
		retry++;
		if(retry<10)
			goto lp1_retry;
		else
			goto exit;
	}
	int retry_ota=0;
lp2_retry:
	i=0;dat=0;retry =0;ret =0;retry_ota = 0;
	fseek(fp_out,sizeof(BOOTLOADER_UPDATE_FILE_HDR_S),SEEK_SET);
	fseek(fp_bin,0,SEEK_SET);
	while( i < ota_header.bin_len)
	{
		if( (ret = fread(&dat,1,1,fp_bin)) == 1)
		{	
			retry = 0;
			if( (ret = fwrite(&dat,1,1,fp_out)) ==1 )
			{
				retry_ota = 0;
				i++;
			}
			else
			{
				printf("fwrite %s err %d\n",ota_file_name,retry_ota);
				retry_ota++;
				if(retry_ota<10)
					goto lp2_retry;
				else
					goto exit;
			}
		}
		else
		{
			printf("fread %s err %d\n",file_name,retry);
			retry++;
			if(retry<10)
				goto lp2_retry;
			else
				goto exit;
		}
	}
	
	if(fseek(fp_out,0,SEEK_END) != 0)
	{
		printf("fseek file err\n");
		goto exit;
	}
	unsigned int out_bin_num = ftell(fp_out);
	
	if( out_bin_num != (ota_header.bin_len) + sizeof(BOOTLOADER_UPDATE_FILE_HDR_S))
	{
		printf("create ota file fail !!!\n");
		goto exit;
	}
	retry=0;BOOTLOADER_UPDATE_FILE_HDR_S ota_header_bak;
lp3_retry:
	fseek(fp_out,0,SEEK_SET);
	memset(&ota_header_bak,0,sizeof(BOOTLOADER_UPDATE_FILE_HDR_S));
	fread(&ota_header_bak,sizeof(BOOTLOADER_UPDATE_FILE_HDR_S),1,fp_out);
	if(memcmp(&ota_header_bak,&ota_header,sizeof(BOOTLOADER_UPDATE_FILE_HDR_S)) != 0)
	{
		printf("create ota file haeder err !!!\n");
		goto exit;
	}
	printf("######### %s info ############\n",ota_file_name);
	printf("header_flag: %X\n",ota_header.header_flag);
	printf("sw_version : %X\n",ota_header.sw_version);
	printf("bin_len    : %X\n",ota_header.bin_len);
	printf("bin_sum    : %X\n",ota_header.bin_sum);
	printf("head_sum   : %X\n",ota_header.head_sum);
	printf("tail_flag  : %X\n",ota_header.tail_flag);
	printf("###############################\n");
	printf("create ota file success !!!\n");
	
exit:
	if(ota_file_name !=NULL)
	{
		free(ota_file_name);ota_file_name =NULL;
	}
	if(fp_out != NULL)
		fclose(fp_out);
	if(fp_bin != NULL)
		fclose(fp_bin);
	return 0;
}

make_ota_bin.c 和要升级的bin文件放在同一级目录下如下图执行
在这里插入图片描述
用二进制对比文件可以看见新生成的bin添加了头部信息,而其他部分一样
在这里插入图片描述

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值