Chinaunix首页 | 论坛 | 博客
  • 博客访问: 15316985
  • 博文数量: 2005
  • 博客积分: 11986
  • 博客等级: 上将
  • 技术积分: 22535
  • 用 户 组: 普通用户
  • 注册时间: 2007-05-17 13:56
文章分类

全部博文(2005)

文章存档

2014年(2)

2013年(2)

2012年(16)

2011年(66)

2010年(368)

2009年(743)

2008年(491)

2007年(317)

分类: LINUX

2008-06-02 09:57:00

//文件拼接,长度添加和文件扩充工具fattach源码fattach.c -- gliethttp_20080602
//gcc -o fattach fattach.c;strip -s fattach
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
#include <stdlib.h>

#define GLIETHTTP_DEBUG
#undef GLIETHTTP_DEBUG

#define mode_insert 1
#define mode_replace 2
#define mode_pad 3
#define mode_fill 4
typedef struct _inode
{
    char *name;
    int append;
    int append_pos;
    int fill;
    char fill_char;
    int fill_len;
    struct _inode *next;
}inode;

inode *new_inode(void)
{
    inode *pinode;
    pinode = (inode *)malloc(sizeof(*pinode));
    memset(pinode, 0, sizeof(*pinode));
    return pinode;
}

void free_inode(inode *head)
{
    inode *tmp;
    do
    {
        tmp = head->next;
        free(head);
        head = tmp;
    }while(head);
}

#define help_string \
"\
fcat out_name a.bin -a b.bin -r0x10 c.bin -i0x80 d.bin -p0x00_0x10000 e.bin -p0xff_0x10000 f.bin -f0x00_0x1000 g.bin -f0xff_f0x1000 k.bin <-e>\n \
1.将长度插入到文件头\n\
  fattach out.bin -a input.bin\n\
2.将长度插入到文件的指定位置,比如第16字节偏移处\n\
  fattach out.bin -i0x10 input.bin或者\n\
  fattach out.bin -i16 input.bin\n\
3.将长度填入文件的指定位置,比如第8字节偏移处\n\
  fattach out.bin -r0x8 input.bin或者\n\
  fattach out.bin -r8 input.bin\n\
4.将文件扩大到指定大小,中间填充执行字符,比如将100字节的文件扩大到1M,中间填充0xaa\n\
  fattach out.bin -f0xaa_0x100000 input.bin或者\n\
  fattach out.bin -f0xaa_1048576 input.bin\n\
5.扩充之后将长度添加到文件结尾,比如将158字节的文件扩大到1k,中间填充0xff,然后将长度加到结尾\n\
  fattach out.bin -p0xff_0x1000 input.bin或者\n\
  fattach out.bin -p0xff_1024 input.bin\n\
6.将多个文件拼接在一起,第一个文件的长度放在0x10偏移处,第2..以后的文件长度放在文件头部,最后以0xffffffff长度为文件链结尾标志\n\
  比如:obm.bin blob.bin gzip_bitmap1.gz gzip_bitmap2.gz gzip_bitmap3.gz gzip_bitmap4.gz几个文件拼接起来\n\
  fattach out.bin -r0x10 obm.bin -a blob.bin -a gzip_bitmap1.gz -a gzip_bitmap2.gz -a gzip_bitmap3.gz -a gzip_bitmap4.gz -e\n\
"


void print_help(void)
{
    printf(help_string);
}

int do_write(int handle, void *buf, int len)
{
    if( write(handle, buf, len) != len )
    {
        printf("Error:the counts of writing not the same with expected\n");
        return -1;
    }
    return 0;
}

static int no_end = 1;
int main(int argc, char *argv[])
{
    inode *pinode,*head;
    int file_handle;
    int out_handle;
    struct stat sbuf;
    char *mmap_buf_file;

    if(argc > 1)
    {
        int i;
        char *name;
        
        if(argc < 3)
        {
            name = argv[1];
            if(name[0] == '-')
            {
                switch(name[1])
                {
                    case 'v':
                    case 'V':
                        printf("%s %s \n", __DATE__, __TIME__);
                        goto EXIT_OK;
                }
            }
            print_help();
            goto EXIT_OK;
        }

        head = pinode = new_inode();

        for(i = 1;i < argc;i++)
        {
            name = argv[i];
            if(name[0] == '-')
            {
                switch(name[1])
                {
                    case 'a':
                    case 'A':
                        pinode->append = mode_insert;
                        pinode->append_pos = 0;
                        continue;
                    case 'i':
                    case 'I':
                        if(pinode->append == 0)pinode->append = mode_insert;
                    case 'r':
                    case 'R':
                        if(pinode->append == 0)pinode->append = mode_replace;
                        pinode->append_pos = strtol(&name[2],NULL,0);
                        #if 0
                        if( (errno == ERANGE) || (errno == EINVAL) )
                        {
                            printf("Error %s : %s \n", name, strerror(errno));
                            goto EXIT_OK1;
                        }
                        #endif
                        continue;
                    case 'p':
                    case 'P':
                        if(pinode->fill == 0)pinode->fill = mode_pad;
                    case 'f':
                    case 'F':
                        if(pinode->fill == 0)pinode->fill = mode_fill;
                        char tmp[5];
                        char *src,*dst;
                        int i;
                        
                        src = &name[2];
                        dst = tmp;
                        for(i = 0;i < 4;i++)
                         *dst++ = *src++;
                        *dst = 0;

                        pinode->fill_char = strtol(tmp,NULL,0);
                        pinode->fill_len = strtol(&name[7],NULL,0);//-p0xa5_0x1000
                        continue;
                    case 'e':
                    case 'E':
                        no_end = 0;
                        continue;
                }
            }
            pinode->name = name;
            pinode->next = new_inode();
            pinode = pinode->next;
        }
        
        if(head->append || head->fill)
        {
            printf("Error:not find output name\n");
            print_help();
            goto EXIT_OK1;
        }
        for(pinode = head->next;pinode->name;pinode = pinode->next)
        {
            if(strcmp(head->name, pinode->name) == 0)
            {
                printf("Error:%s : output name should not be the same with input file !\n", head->name);
                print_help();
                goto EXIT_OK1;
            }
            #ifdef GLIETHTTP_DEBUG
            printf("#%s : %s\n", pinode->append? "true ":"false", pinode->name);
            #endif
            file_handle = open(pinode->name, O_RDONLY);
            if(file_handle < 0)
            {
                printf("Error:could not open %s : %s\n", pinode->name, strerror(errno));
                goto EXIT_OK1;
            }
            close(file_handle);
        }
        
        out_handle = open(head->name, O_RDWR|O_CREAT|O_TRUNC, 0666);
        if(out_handle < 0)
        {
            printf("Error:could not create file : %s : %s \n", head->name, strerror(errno));
            goto EXIT_OK1;
        }
        
        for(pinode = head->next;pinode->name;pinode = pinode->next)
        {
            file_handle = open(pinode->name, O_RDONLY);
            if (fstat(file_handle, &sbuf) < 0)
            {
                printf("Error:could not stat %s : %s \n", pinode->name, strerror(errno));
                goto EXIT_OK2;
            }

            mmap_buf_file = (char *)mmap(0, sbuf.st_size,PROT_READ, MAP_SHARED, file_handle, 0);
            if(mmap_buf_file == (char*)MAP_FAILED)
            {
                close(file_handle);
                printf("Error:could not mmap %s : %s\n", pinode->name, strerror(errno));
                goto EXIT_OK2;
            }
                        
            if(pinode->append)
            {
                #ifdef GLIETHTTP_DEBUG
                printf("append_pos = %d\n", pinode->append_pos);
                #endif
                if( (pinode->append_pos > sbuf.st_size) )
                {
                    printf("Error:-m%d outof file size %d\n", pinode->append_pos, sbuf.st_size);
                    goto EXIT_OK3;
                }
                if( do_write(out_handle, mmap_buf_file, pinode->append_pos) )
                {
                    goto EXIT_OK3;
                }
                if( do_write(out_handle, &sbuf.st_size, sizeof(sbuf.st_size)) )
                {
                    goto EXIT_OK3;
                }
                if(pinode->append == mode_insert)
                {
                    //if( (pinode->append_pos + sizeof(sbuf.st_size) ) < sbuf.st_size )
                    {
                        if( do_write(out_handle,
                                    &mmap_buf_file[pinode->append_pos],
                                    sbuf.st_size - pinode->append_pos
                                    )
                          )
                        {
                            goto EXIT_OK3;
                        }
                    }
                }
                else
                {
                    if( (pinode->append_pos + sizeof(sbuf.st_size) ) < sbuf.st_size )
                    {
                        if( do_write(out_handle,
                                    &mmap_buf_file[pinode->append_pos] + sizeof(sbuf.st_size),
                                    sbuf.st_size - pinode->append_pos - sizeof(sbuf.st_size)
                                    )
                          )
                        {
                            goto EXIT_OK3;
                        }
                    }
                }
            }
            else
            if( do_write(out_handle, mmap_buf_file, sbuf.st_size) )
            {
                goto EXIT_OK3;
            }

            if(pinode->fill)
            {
                char *malloc_buf;
                int malloc_len;

                if(pinode->fill_len > sbuf.st_size)
                {
                    malloc_len = pinode->fill_len - sbuf.st_size;
                    if(pinode->fill == mode_pad)malloc_len -= sizeof(sbuf.st_size);
                    malloc_buf = malloc(malloc_len);
                    memset(malloc_buf, pinode->fill_char, malloc_len);

                    if( do_write(out_handle, malloc_buf, malloc_len) )
                    {
                        free(malloc_buf);
                        goto EXIT_OK3;
                    }
                    free(malloc_buf);
                }

                if(pinode->fill == mode_pad)
                {
                    //将长度追加到文件尾[gliethttp_20080602]
                    if( do_write(out_handle, &sbuf.st_size, sizeof(sbuf.st_size)) )
                    {
                        goto EXIT_OK3;
                    }
                }
            }
            
            munmap((void *)mmap_buf_file, sbuf.st_size);
            close(file_handle);
        }
        //最后追加0xffffffff作为长度域用来标识重复文件链的结尾
        if(no_end == 0)
        {
            long tmp_len = 0xffffffff;
            if ( write(out_handle, &tmp_len, sizeof(tmp_len)) != sizeof(tmp_len) )
            {
                printf("Error:the counts of writing not the same with expected\n");
                goto EXIT_OK2;
            }
        }
        close(out_handle);
        goto EXIT_OK1;
    }
    print_help();
    goto EXIT_OK;
EXIT_OK3:
    munmap((void *)mmap_buf_file, sbuf.st_size);
EXIT_OK2:
    close(file_handle);
    close(out_handle);
    remove(head->name);
EXIT_OK1:
    free_inode(head);
EXIT_OK:
    return 0;
}


文件:fattach.tar.gz
大小:5KB
下载:下载

阅读(1539) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~