Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1296699
  • 博文数量: 196
  • 博客积分: 4141
  • 博客等级: 中将
  • 技术积分: 2253
  • 用 户 组: 普通用户
  • 注册时间: 2009-03-21 20:04
文章存档

2019年(31)

2016年(1)

2014年(16)

2011年(8)

2010年(25)

2009年(115)

分类: C/C++

2009-10-22 19:20:54


/********************************************************************************/
/*                                                                                                                     */
/* 为bochs写的一个镜像工具                                                                             */
/*                                                                                                                    */
/* creat -t hd/fd -s xxx(k/m/g) -o xxx.img                                                       */
/* ps: size 大小为最大4g                                                                                   */
/*                                                                                                                    */
/* write -H xxx -S xxx -C xxx -i xxx -o xxx.img                                                */
/********************************************************************************/

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

#define FILE_NAME_LEN 128

#define LINE_BUFFER_SIZE 1000
char line[LINE_BUFFER_SIZE];

/********************************************************************************/
/* 函数原型声明 */
/********************************************************************************/
int img_creat(struct cmd_struct * cmd_s);
int img_write(struct cmd_struct * cmd_s);

/********************************************************************************/
/* 命令和脚本解释信息 */
/********************************************************************************/
/* 命令类型 */
#define CMD_CREAT 0
#define CMD_WRITE 1

/* 磁盘类型 */
#define NULL_TYPE 0
#define HD_TYPE 1
#define FD_TYPE 2

char img_cmd[][10] = {"creat", "write"};
int (*func_handler[])(struct cmd_struct * cmd_s) =
{
    img_creat,
    img_write
};

struct cmd_struct
{
    int cmd_type; // 命令类型

    int disk_type; // 磁盘类型

    long long size; // 大小

    int shead; // 起始磁头

    int scyl; // 起始柱面

    int ssector; // 起始扇区

    char infile[FILE_NAME_LEN + 1];
    char outfile[FILE_NAME_LEN + 1];
};

/********************************************************************************/
/* 创建镜像 */
/********************************************************************************/
long long heads = 16;
long long spt = 63;

int img_creat(struct cmd_struct * cmd_s)
{
    char bochsrc_line[1000];

    if (cmd_s->disk_type == HD_TYPE)
    {
        sprintf(bochsrc_line, "ata0-master: type=disk, path=\"%s\", mode=%s, cylinders=%lld, heads=%lld, spt=%lld", cmd_s->outfile, "flat", cmd_s->size / heads / spt / 512, heads, spt);
    }
    else if (cmd_s->disk_type == FD_TYPE)
    {
        printf("抱歉,未实现!\n");
        exit(0);
    }

    FILE *fp = fopen(cmd_s->outfile, "w");
    if (fp == NULL)
    {
        printf("文件打开错误\n");
        exit(1);
    }

    cmd_s->size = cmd_s->size / 63 / 16 / 512 * 63 * 16 * 512;
    long long disksize = cmd_s->size;
    while(disksize > 0)
    {
        long long temp = (long)((disksize < 41943030) ? disksize : 41943030);
        fseek(fp, (int)temp, SEEK_CUR);
        disksize -= temp;
    }
    fseek(fp, -1, SEEK_CUR);
    if (fputc('\0', fp) == EOF)
    {
        fclose(fp);
        printf("ERROR: The disk image is not complete! (image larger then free space?)\n");
        exit(1);
    }
    fclose(fp);

    printf("\nThe following line should appear in your bochsrc:\n");
    printf(" %s\n", bochsrc_line);

    return 0;
}

/********************************************************************************/
/* 写镜像 */
/********************************************************************************/
int img_write(struct cmd_struct * cmd_s)
{
#define BUFFER_NUM 100000
    long long offset;
    int num;
    char buffer[BUFFER_NUM];

    FILE *inf, *outf;

    if ((inf = fopen(cmd_s->infile, "r+b")) == NULL)
    {
        printf("输入文件有误:%s.\n", line);
        exit(1);
    }
    if ((outf = fopen(cmd_s->outfile, "r+b")) == NULL)
    {
        printf("输出文件有误:%s.\n", line);
        exit(1);
    }
    
    /* 磁盘寻址 */
    offset = cmd_s->scyl * heads * spt + cmd_s->shead * spt + cmd_s->ssector - 1;
    offset = offset * 512;
    while(offset > 0)
    {
        long long temp = (long)((offset < 41943030) ? offset : 41943030);
        fseek(outf, (int)temp, SEEK_CUR);
        offset -= temp;
    }

    while ((num = fread(buffer, sizeof(char), BUFFER_NUM, inf)) != 0)
    {
        if (fwrite(buffer, sizeof(char), num, outf) != num)
        {
            printf("fwrite执行错误\n");
            exit(1);
        }
    }

    fclose(inf);
    fclose(outf);

    return 0;
}

/********************************************************************************/
/* 脚本解释器 */
/********************************************************************************/
int parse_cmdline(char *line, struct cmd_struct * cmd_s)
{
    int i, num_of_cmd;
    char *arg = line;
    char cmd[LINE_BUFFER_SIZE];

    char str[10];
    char contents[128];

    sscanf(arg, "%s", cmd);
    arg += strlen(cmd);
    num_of_cmd = sizeof(img_cmd) / sizeof(img_cmd[0]);

    for (i = 0; i < num_of_cmd; ++i)
    {
        if (strcmp(img_cmd[i], cmd) == 0)
        {
            cmd_s->cmd_type = i;
            break;
        }
    }
    if (i == num_of_cmd)
    {
        printf("无效指令:%s\n", cmd);
        exit(0);
    }

    while (strlen(arg) != 0)
    {
        sscanf(arg, "%s", str);
        if (str[0] != '-')
        {
            printf("错误的提示符格式:%s\n", str);
            exit(0);
        }

        while (arg[0] == ' ')
            ++arg;
        arg = arg + strlen(str);
        sscanf(arg, "%s", contents);
        while (arg[0] == ' ')
            ++arg;
        arg = arg + strlen(contents);

        switch(str[1])
        {
        case 't':

            if (strcmp(contents, "fd") == 0)
                cmd_s->disk_type = FD_TYPE;
            else if (strcmp(contents, "hd") == 0)
                cmd_s->disk_type = HD_TYPE;
            else
            {
                printf("错误的磁盘类型格式:%s\n", line);
                exit(0);
            }
            break;
        case 's':
            if (cmd_s->disk_type == 0)
            {
                printf("请先指定磁盘类型.\n");
                exit(0);
            }

            if (cmd_s->disk_type == HD_TYPE)
            {
                if (contents[strlen(contents) - 1] == 'k')
                {
                    cmd_s->size = 1024;
                    contents[strlen(contents) - 1] = '\0';
                }
                else if (contents[strlen(contents) - 1] == 'm')
                {
                    cmd_s->size = 1024 * 1024;
                    contents[strlen(contents) - 1] = '\0';
                }
                else if (contents[strlen(contents) - 1] == 'g')
                {
                    cmd_s->size = 1024 * 1024 * 1024;
                    contents[strlen(contents) - 1] = '\0';
                }
                else
                {
                    cmd_s->size = 1;
                }
                
                cmd_s->size = cmd_s->size * (long long)atoi(contents);
                if (cmd_s->size >= (long long)4 * 1024 * 1024 * 1024)
                {
                    printf("文件大小超过上限。");
                    exit(0);
                }
            }
            else if (cmd_s->disk_type == FD_TYPE)
            {
                /*未实现*/
            }
            break;
        case 'o':
            if (strlen(contents) >= FILE_NAME_LEN)
            {
                printf("输出文件名太长,只能在128个字符以内。\n");
                exit(0);
            }
            strcpy(cmd_s->outfile, contents);
            break;
        case 'i':
            if (strlen(contents) >= FILE_NAME_LEN)
            {
                printf("输入文件名太长,只能在128个字符以内。\n");
                exit(0);
            }
            strcpy(cmd_s->infile, contents);
            break;
        case 'H':
            cmd_s->shead = atoi(contents);
            break;
        case 'S':
            cmd_s->ssector = atoi(contents);
            break;
        case 'C':
            cmd_s->scyl = atoi(contents);
            break;
        default:
            printf("未指定提示符类型:%c\n", str[1]);
            exit(0);
            break;
        }
    }

    return 0;
}

int main(int argc, char *argv[])
{
    FILE *conf_fp;
    char filename[FILE_NAME_LEN];

    if (argc != 2)
    {
        printf("错误的输入参数格式\n");
        return 0;
    }

    if (strlen(argv[1]) >= FILE_NAME_LEN)
    {
        printf("文件名太长,只能在128个字符以内。\n");
        return 0;
    }
    strcpy(filename, argv[1]);

    if ((conf_fp = fopen(filename, "r")) == NULL)
    {
        printf("配置文件不存在");
        return 0;
    }

    struct cmd_struct cmd_s;
    
    while (fgets(line, LINE_BUFFER_SIZE, conf_fp) != NULL)
    {
        parse_cmdline(line, &cmd_s);
        func_handler[cmd_s.cmd_type](&cmd_s);
    }

    return 0;
}


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