/********************************************************************************/
/* */
/* 为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;
}
|