📄 ddcopy16.cpp
字号:
* "cmd" must be Diskread(0x42) or Diskwrite(0x43)
* @return >=0: 成功,读写的数据块数
* @return -1: 失败
*/
short _diskop (unsigned char drv, unsigned char cmd,
unsigned char * buffer, unsigned long startlow, unsigned short copyblks)
{
/* 磁盘存取数据包结构 */
struct disk_address_packet {
unsigned char size_of_packet;
unsigned char reserved;
unsigned short number_of_blocks_to_transfer;
unsigned short transfer_buffer_offset;
unsigned short transfer_buffer_segment;
unsigned long starting_absolute_block_low;
unsigned long starting_absolute_block_high;
};
struct disk_address_packet dap;
unsigned char av;
unsigned char * pt = (unsigned char *) &dap;
dap.size_of_packet = sizeof (dap);
dap.reserved = 0;
dap.number_of_blocks_to_transfer = copyblks;
dap.transfer_buffer_offset = FP_OFF(buffer);
dap.transfer_buffer_segment = FP_SEG(buffer);
dap.starting_absolute_block_low = startlow;
dap.starting_absolute_block_high = 0;
asm {
push ds
push si
mov ah, cmd
mov dl, drv
lds si, DWORD PTR pt
int 13h
pop si
pop ds
mov av, ah
jc error
}
return (dap.number_of_blocks_to_transfer);
error:
// printf ("(%02X) ", av);
ErrorNum = av;
return (-1);
}
/**
* 读取指定硬盘信息
* @param drv 硬盘ID号: 80h, 81h, ...
* @param df 硬盘信息结构指针
* @return 0 成功
* @return -1 失败
*/
short _get_disk_info (unsigned char drv, struct _diskinfo * df)
{
unsigned char av;
unsigned char * p = (unsigned char *) df;
/* 数据块长度 */
df->size_of_buffer = 0x1a;
asm {
push ds
push si
mov ah, 48h
mov dl, drv
lds si, DWORD PTR p
int 13h
pop si
pop ds
mov av, ah
jc error
}
return (0);
error:
return (-1);
}
/**
* 读取指定硬盘信息
* @param disk 硬盘序号: 1, 2, ...
* @param start 硬盘开始扇区.
* @param sector 硬盘扇区总数.
* @return 0 成功;
* @return -1 失败.
*/
short get_disk_info (short disk, unsigned long * start, unsigned long * sector)
{
struct _diskinfo df;
// 读指定的硬盘参数
if (_get_disk_info (disk+0x7f, &df)){
return (-1);
}
// 设置硬盘总扇区数
sector[0] = df.total_number_of_sectors_low;
// 设置起始扇区
start[0] = 0L;
return (0);
}
/**
* 读取指定硬盘的指定分区信息
* @param disk 硬盘序号: 1, 2, ...
* @param part 分区序号.
* @param start 分区的开始扇区.
* @param sector 分区的扇区总数.
* @return 0 成功;
* @return -1 失败.
*/
short get_disk_part_info (short disk, short part, unsigned long * start, unsigned long * sector)
{
unsigned char buffer [512];
unsigned char partition_records[64];
struct _partinfo {
unsigned char boot_indicator;
unsigned char partition_start_head;
unsigned char partition_start_sector;
unsigned char partition_start_track;
unsigned char operating_system_indicator;
unsigned char partition_end_head;
unsigned char partition_end_sector;
unsigned char partition_end_track;
unsigned long sectors_preceding_partition;
unsigned long length_of_partition_in_sectors;
} * _partinfo = (struct _partinfo *) partition_records;
// 读入硬盘第一扇区
if (0 >= _diskop ((unsigned char) disk+ 0x7f, 0x42, buffer, 0, 1)){
// 主引导扇区读错误
printf ("Error read MBR (Main Boot Record) on disk %x.\n", disk);
return (-1);
}
// 判断主引导扇区是否可用
if (buffer [510] != 0x55 || buffer [511] != 0xAA){
// 主引导扇区标志错
printf ("Invalid MBR (Main Boot Record) flag (%02X%02X)!\n", buffer[510], buffer[511]);
return (-1);
}
// 读入分区信息表
memcpy (partition_records, &buffer[446], 64);
// 设置指定分区的起始扇区和所占扇区数
start[0] = _partinfo[part-1].sectors_preceding_partition;
sector[0] = _partinfo[part-1].length_of_partition_in_sectors;
return (0);
}
/**
* 显示所有硬盘的信息
*/
void show_disks_info (void)
{
short i, j;
for (i=1; ; i++){
if (get_disk_info (i, &starts[0], §ors[0])){
break;
} else {
printf ("\nDisk %d, total size %ld MB\n", i, sectors[0]/2048);
for (j=1; j<=4; j++){
starts[0] = sectors[0] = 0;
get_disk_part_info (i, j, &starts[0], §ors[0]);
printf (" Partition %d, size of partition: %ld MB\tsectors preceding: %ld\n",
j, sectors[0]/2048L, starts[0]);
}
}
}
}
/**
* 分析程序命令行参数
*/
void read_args (char * args)
{
char arg0[CMDBUFF], arg1[CMDBUFF], arg2[CMDBUFF];
char res[CMDBUFF], res1[CMDBUFF], res2[CMDBUFF];
char sour[CMDBUFF], dest[CMDBUFF];
char * endptr;
short i, j;
while (1 != sscanf (args, "%s -%[^-] %[^\n]", arg0, arg1, arg2)){
if (arg1[0] == 'y'){
conf.confirm = 0;
} else if (arg1[0] == 'h'){
conf.printhelp = PR_CMDLINE | PR_OPTIONS |PR_EXAMPLE;
break;
} else if (arg1[0] == 's'){
conf.showinfo = 1;
break;
} else if (arg1[0] == 'f'){
conf.defaultmode = 1;
conf.diskmode = 1;
break;
} else if (arg1[0] == 'c'){
conf.compress= 1;
} else if (arg1[0] == 'v'){
if (2 == sscanf (arg1, "%s %s ", res1, res2)){
if (sscanf (res2, "%[0-9] ", res) && strlen (res) == strlen(res2)){
conf.imgsize = atoi (res);
} else {
conf.printhelp = PR_CMDLINE | PR_OPTIONS |PR_EXAMPLE;
}
}
} else if (arg1[0] == 'e'){
if (2 == sscanf (arg1, "%s %s ", res1, res2)){
if (sscanf (res2, "%[0-9] ", res) && strlen (res) == strlen(res2)){
conf.copysectors = strtoul (res, &endptr, 10);
} else {
conf.printhelp = PR_CMDLINE | PR_OPTIONS |PR_EXAMPLE;
}
}
} else if (arg1[0] == 'd'){
// 磁盘拷贝模式
conf.diskmode = 1;
if (2 == sscanf (arg1, "%*s s = %s d = %[^\n] ", sour, dest)){
// 读入源参数信息
if (sscanf (sour, "%[0-9] ", res) && strlen (res) == strlen (sour)){
disks [0] = atoi (sour);
} else {
imgfiles[0] = strdup (sour);
}
i = 1;
j = 1;
// 读入目标参数信息
while (sscanf(dest, "%[^,] , %[^\n] ", res, dest)){
// 去除末尾的空格
while (dest[strlen(dest)-1] == ' '){
dest[strlen(dest)-1] = 0;
}
while (res [strlen(res)-1] == ' '){
res[strlen(res)-1] = 0;
}
if (sscanf (res, "%[0-9]", res1) && strlen (res) == strlen (res1)){
disks [i++] = atoi (res);
} else {
imgfiles [j++] = strdup (res);
}
if (strcmp (res, dest) == 0){
break;
}
}
}
else {
conf.printhelp = PR_CMDLINE | PR_OPTIONS |PR_EXAMPLE;
break;
}
}
else if (arg1[0] == 'p'){
// 分区拷贝模式
conf.diskmode = 0;
if (2 == sscanf (arg1, "%*s s = %s d = %[^\n] ", sour, dest)){
// 读入源参数信息
if (sscanf (sour, "%[0-9: ] ", res) && strlen (res) == strlen (sour)){
if (2 != sscanf (sour, "%[0-9] : %[0-9] ", res, res1)){
// 分区参数不完整
printf ("Invalid source parameters:(%s)\n", arg1);
conf.printhelp = PR_CMDLINE | PR_OPTIONS |PR_EXAMPLE;
break;
}
disks [0] = atoi (res);
parts [0] = atoi (res1);
} else {
imgfiles[0] = strdup (sour);
}
i = 1;
j = 1;
// 读入目标参数信息
while (sscanf(dest, "%[^,] , %[^\n] ", res, dest)){
// 去除末尾的空格
while (dest[strlen(dest)-1] == ' '){
dest[strlen(dest)-1] = 0;
}
while (res [strlen(res)-1] == ' '){
res[strlen(res)-1] = 0;
}
if (sscanf (res, "%[0-9: ]", res1) && strlen (res) == strlen (res1)){
sscanf (res, "%[0-9] : %[0-9] ", res1, res2);
disks [i] = atoi (res1);
parts [i++] = atoi (res2);
} else {
imgfiles[j++] = strdup (res);
}
if (strcmp (res, dest) == 0){
break;
}
}
}
else {
conf.printhelp = PR_CMDLINE | PR_OPTIONS |PR_EXAMPLE;
break;
}
}
else {
printf ("Bad option: -%c\n", arg1[0]);
conf.printhelp = PR_CMDLINE | PR_OPTIONS |PR_EXAMPLE;
break;
}
sprintf (args, "%s %s", arg0, arg2);
arg2[0] = 0;
}
}
void show_data (void)
{
short i = 0;
printf ("\n");
if (disks[0]){
if (conf.diskmode){
printf ("Sour disk %d, size %ld MB.\n", disks[0], sectors[0]/2048L);
} else {
printf ("Sour disk %d partition %d, begin sector %ld, size %ld MB.\n",
disks[0], parts[0], starts[0], sectors[0]/2048L);
}
} else {
printf ("Sour imgfile %s\n", imgfiles[0]);
}
for (i=1; disks[i]; i++){
if (conf.diskmode){
printf ("Dest disk %d, size %ld MB.\n", disks[i], sectors[i]/2048L);
} else {
printf ("Dest disk %d partition %d, begin sector %ld, size %ld MB.\n",
disks[i], parts[i], starts[i], sectors[i]/2048L);
}
}
for (i=1; imgfiles[i]; i++){
printf ("Dest imgfile %s\n", imgfiles[i]);
}
printf ("\n");
}
// 判断文件是否存在
// 0: 不存在
// 1: 存在
short file_exists (char * filename)
{
FILE * FP;
short ret;
FP = fopen (filename, "rb");
if (FP == NULL){
ret = 0;
} else {
ret = 1;
fclose (FP);
}
return (ret);
}
// 读源数据文件
// 返回读入的数据块数 blocks (512 bytes)
short read_sour_file (unsigned char * buffer)
{
unsigned char * buf;
unsigned long size, csize;
unsigned char c;
short blks;
readnextvol:
// 读入数据块压缩状态标志到 c 中
if (fread (&c, 1, 1, FILES[0]) != 1){
// 未读到数据文件标志
printf ("Bad source file flag.\n");
return (-1);
}
if (c == 0xaa){
// 遇到数据文件结束标志:0xaa
return (0);
} else if (c > 1){
// 当前文件存在分卷 (c 表示下一分卷序号)
// 关闭当前源数据文件
fclose (FILES[0]);
// 生成下一分卷文件名
sprintf (imgfiles[0]+strlen(imgfiles[0])-2, "%02d", c-1);
// 打开下一分卷
if (NULL == (FILES[0] = fopen (imgfiles[0], "rb"))){
perror (imgfiles[0]);
return (-1);
}
// 重新读入数据压缩标志
goto readnextvol;
} else{ // c==1 || c==0
// 读入数据块大小到 size 中
size = 0;
if (fread (&size, 2, 1, FILES[0]) != 1){
// 数据异常
printf ("Data error (1)!\n");
return (-1);
}
if (size > (Blocks << 9)){
// 数据异常
printf ("Data block is too large! (%d)\n", size);
printf ("The image file may be changed!\n");
return (-1);
}
if (c == 1){
buf = (unsigned char *) malloc ((size_t) size);
if (buf == NULL){
perror ("buf");
return (-1);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -