目的:完成多个bin文件的合并,并执行相关偏移地址
编译:Linux环境下使用gcc进行编译
生成可执行文件:
linux的可执行文件:gcc main.c -o binMerge.exe
windows的可执行文件:i686-w64-mingw32-gcc main.c -o bin_merge_Select.exe
(需要安装MinGW:sudo apt-get install mingw-w64)

exe使用方式:./binMerge_T taget1.bin target2.bin target3.bin 0x0000000 0x10000000 0x20000000 merge.bin

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <inttypes.h>
#include <stdlib.h>
#define READ_LEN    (1024)  /*读取长度*/
#define FILL    (uint8_t)0xff   /*填充字符*/


//#define DEBUG

int cmp(const void* a, const void* b);
int main(int argc,char *argv[])
{
#ifdef DEBUG
argc = 8;
argv[1] = "./b.bin";
argv[2] = "./c.bin";
argv[3] = "./a.bin";
argv[4] = "0x20000";
argv[5] = "0x60000";
argv[6] = "0x0000";
argv[7] = "out1.bin";

#endif
    if(argc <= 4)
    {
        printf("Please enter at least two file names");
        return -1;
    }
    if(argc%2)
    {
        printf("参数缺少,需要为每个bin文件指定偏移地址,并且需要指定一个输出文件名\n");
        return -1;
    }

    printf("选择填充值:1.0xFF 2.0x00\n");
    uint8_t input_val = 0;
    uint8_t fill_value = 0;
    scanf("%d",&input_val);
    if(input_val == 1){
        fill_value = FILL;
    }else if(input_val == 2){
        fill_value = 0;
    }else{
        fill_value = FILL;
    }

    uint8_t read_buf[READ_LEN];/*读取缓冲*/
    uint8_t fill_byte = fill_value;/*填充字节*/
    uint8_t fill_array[READ_LEN] = {[0 ... READ_LEN-1] = FILL};/*填充数组*/
    memset(fill_array,fill_value,sizeof(fill_array));
    char output_filename[128];

    /*文件数*/
    uint8_t file_num = (argc-2)/2;
    /*偏移地址数组*/
    uint32_t offset[file_num];
    uint32_t offset_sort[file_num];
    /*文件*/
    FILE *file[file_num];
    /*文件名*/
    char *filename[file_num];
    char *sort_filename[file_num];

    /*所有值初始化*/
    memset(offset,0,sizeof(offset));
    memset(offset_sort,0,sizeof(offset_sort));
    memset(file,0,sizeof(file));
    memset(filename,0,sizeof(filename));
    /*获取输出文件名*/
    strcpy(output_filename,argv[argc-1]);
    /*获取文件名和偏移地址*/
    for(int i = 0;i < file_num;i++)
    {
        char* endptr;
        filename[i] = argv[i+1];
        offset[i] = strtoimax(argv[i+1+file_num],&endptr,0);
    }
    memcpy(offset_sort,offset,sizeof(offset));
    /*偏移地址大小排序,从最小地址开始偏移*/
    qsort(offset_sort,sizeof(offset_sort)/sizeof(uint32_t),sizeof(uint32_t),cmp);
    /*根据偏移地址进行文件对应排序*/
    for(int i = 0;i < sizeof(offset_sort)/sizeof(uint32_t);i++)
    {
        for(int j = 0;j < sizeof(offset_sort)/sizeof(uint32_t);j++)
        {
            if(offset_sort[i] == offset[j])
            {
                sort_filename[i] = filename[j];
                break;
            }
        }
    }
    /*打开需要生成的文件*/
    FILE *fp_save = fopen(output_filename,"wb+"); 
    if(fp_save == NULL)
    {
        perror("fopen fail");
        return -1;
    }

    for(int i = 0;i < file_num;i++)
    {
        file[i] = fopen(sort_filename[i],"rb");
        if(file[i] == NULL)
        {
            printf("open %s failed : %s\n", sort_filename[i],strerror(errno));
            remove(output_filename);
            return -1;            
        }


        /*填充:将目标文件填充默认值*/
        while((offset_sort[i] - ftell(fp_save)) > READ_LEN)
        {
            uint16_t write_len = fwrite(fill_array,sizeof(char),READ_LEN,fp_save);
        }
        while(offset_sort[i] - ftell(fp_save))
        {
            uint16_t write_len = fwrite(&fill_byte,sizeof(char),1,fp_save);
        }
        /*复制*/
        while(1)
        {
            uint16_t read_len = fread(read_buf,sizeof(char),READ_LEN,file[i]);
            uint16_t write_len = fwrite(read_buf,sizeof(char),read_len,fp_save);
            if(write_len != read_len)
            {
                perror("fwrite fail");
                fclose(file[i]);
                remove(output_filename);
                return -1;                 
            }
            if(read_len < READ_LEN)
            {
                fclose(file[i]);
                break;    
            }        
        }
        

    }

    fclose(fp_save);

    for(int i = 0;i < file_num;i++)
    {
        printf("%#010X \t%s\n",offset_sort[i],sort_filename[i]);
    }

    return 0;
}

int cmp(const void* a, const void* b)
{
    int arg1 = *(const int*)a;
    int arg2 = *(const int*)b;
 
    if (arg1 < arg2) return -1;
    if (arg1 > arg2) return 1;
    return 0;
 
    // return (arg1 > arg2) - (arg1 < arg2); // 可行的简写
    // return arg1 - arg2; // 错误的简写(若给出 INT_MIN 则会失败)
}

代码源处:https://gitee.com/sharkisyou/bin-merge.git

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐