📄 clone.c
字号:
#include <dos.h>
#include <conio.h>
#include <stdio.h>
#include <string.h>
#define _TC_ 1
#ifndef _TC_
struct REGPACK {
unsigned r_ax, r_bx, r_cx, r_dx;
unsigned r_bp, r_si, r_di;
unsigned r_ds, r_es, r_flags;
};
#endif
char READ = 0x02;
char WRITE = 0x02;
#define MAX_SECTOR_NUMBER 100
#define BYTE unsigned char
#define WORD unsigned int
#define DWORD unsigned long
#define SectorEnd 0xAA55
#define DEFAULT_DISK 0x80
typedef struct BootRecord{
unsigned char Go2BootCode[3];
unsigned char OEMNameVersion[8];
WORD BytesPerSector;
BYTE SectorsPerCluster; /* must be power of 2 */
WORD ReservedSectors;
BYTE CopiesOfFAT;
WORD MaxNumberOfRootEntries;
WORD TotalSectors;
BYTE MediaType;
WORD SectorsInFAT;
WORD SectorsPerTrack;
WORD HiddenSectors;
}BR;
typedef struct PartionTable{
BYTE BootTAG; /*Boot TAG */
BYTE StartHead; /*Starting Head*/
unsigned StartSector:6;
unsigned StartCylinder_H2:2;
unsigned StartCylinder_L8:8;
BYTE SystemID;
BYTE EndHead;
unsigned EndSector:6;
unsigned EndCylinder_H2:2;
unsigned EndCylinder_L8:8;
DWORD RelativeSectors;
DWORD TotalSectors;
}PT;
typedef struct MainBootRecord{
unsigned char Dummy[0x1B0];
WORD blank[7];
PT PT1;
PT PT2;
PT PT3;
PT PT4;
WORD ENDTAG;
}MBR;
char Version[]="Composed by Kuang Yujun, Bupt. 2001/08/17";
#define DISK 0x13
#define _BYTE_ 0x100
int ReadSector(unsigned char *buffer,
BYTE Sectors, DWORD Cylinder, BYTE Header, BYTE Sector, BYTE Driver)
{
struct REGPACK REGs;
REGs.r_es=FP_SEG(buffer);
REGs.r_bx=FP_OFF(buffer);
REGs.r_ax=READ*_BYTE_+Sectors%_BYTE_;
REGs.r_flags=0;
REGs.r_cx=(Cylinder%_BYTE_)*_BYTE_+((Cylinder/_BYTE_)%0x04)*0x40+Sector%0x40;
REGs.r_dx=(Header%_BYTE_)*_BYTE_+Driver%_BYTE_;
intr(DISK, ®s);
if(REGs.r_flags & 1)
return(-(int)REGs.r_ax/_BYTE_);
else
return(Sectors%_BYTE_);
}
int WriteSector(unsigned char *buffer_d,
BYTE Sectors_d, DWORD Cylinder_d, BYTE Header_d, BYTE Sector_d, BYTE Driver_d)
{
struct REGPACK REGs_d;
REGs_d.r_es=FP_SEG(buffer_d);
REGs_d.r_bx=FP_OFF(buffer_d);
REGs_d.r_ax=WRITE*_BYTE_+Sectors_d%_BYTE_;
REGs_d.r_flags=0;
REGs_d.r_cx=(Cylinder_d%_BYTE_)*_BYTE_+((Cylinder_d/_BYTE_)%0x04)*0x40+Sector_d%0x40;
REGs_d.r_dx=(Header_d%_BYTE_)*_BYTE_+Driver_d%_BYTE_;
intr(DISK, ®s_d);
if(REGs_d.r_flags & 1)
return(-(int)REGs_d.r_ax/_BYTE_);
else
return(Sectors_d%_BYTE_);
}
int ReadDiskPara(BYTE Driver,BYTE *TYPE,WORD *MaxCylinder,BYTE *MaxSector,WORD *MaxHead, BYTE *Drivers)
{
struct REGPACK REGs;
REGs.r_ax = 0x0800;
REGs.r_bx = 0x0000;
REGs.r_dx = Driver%_BYTE_;
intr(DISK, ®s);
if(REGs.r_flags & 1)
return(-1);
else{
*TYPE = (BYTE)(REGs.r_bx&0xFF);
*MaxCylinder = ((REGs.r_cx%_BYTE_)/0x40)*_BYTE_+REGs.r_cx/_BYTE_;
*MaxHead = REGs.r_dx/_BYTE_;
*MaxSector = REGs.r_cx%0x40;
*Drivers = REGs.r_dx%_BYTE_;
return(*MaxCylinder);
}
}
unsigned char GetHardDriveIndex(char* driveName)
{
unsigned char HardDrive;
switch(driveName[0]){
case 'A': case 'a': HardDrive = 0x00; break;
case 'B': case 'b': HardDrive = 0x01; break;
case '1': case 'C': case 'c': HardDrive = 0x80; break;
case '2': case 'D': case 'd': HardDrive = 0x81; break;
case '3': case 'E': case 'e': HardDrive = 0x82; break;
case '4': case 'F': case 'f': HardDrive = 0x83; break;
default:{
fprintf(stdout, "\n\tPANIC: not valid diskname given.\n");
exit(-1);
}break;
}
return HardDrive;
}
char ProgressMark(){
static i;
switch(i%8){
case 0: i++; return('-');
case 1: i++; return('-');
case 2: i++; return('\\');
case 3: i++; return('\\');
case 4: i++; return('|');
case 5: i++; return('|');
case 6: i++; return('/');
case 7: i++; return('/');
}
}
int main(int argc, char **argv)
{
MBR MBRs[MAX_SECTOR_NUMBER];
DWORD ii;
BYTE type_s=0,type_d=0;
BYTE maxSector_s,maxSector_d,drivers, maxBlock = MAX_SECTOR_NUMBER /* in sectors */;
BYTE srcHardDrive,dstHardDrive;
WORD maxHead_s,maxHead_d, maxCylinder_s,maxCylinder_d;
DWORD maxSectors=0;
BYTE Sector; WORD Cylinder, Head;
char *fileName=NULL;
char *dstDriveName;
char *srcDriveName;
char *blockSize=NULL;
FILE *fp;
/* char *MSWIN="MSWIN4.1";
char *N1TFS ="NTFS ";
char *BootRecordMSGFormat="\n;At:[%9lu of %9lu]\n;Position:\tHead/Side|Cylinder|Sector|\n[BOOTCODE]\t%9u %8u %6u\n";
char *PartionTableMSGFormat="\n;PartionTable:[%10lu of %10lu]\n;Position:\tHead/Side|Cylinder|Sector|\n[PARTION]\t%9u %8u %6u\n; |ID|A|sHead|sCylind|sSec|eHead|eCylind|eSec|RelativeSectors|TotalSectors|\n";
*/ char *HelpMessage="CLONE: Copy a disk content to another disk.\n\n"\
"Usage:\tCLONE [<Options>] [<-|/><?|h>\n"\
"\t-l\tSpecify <LogFileName>\n"\
"\t-s\tSpecify <srcDriveName>\n"\
"\t-d\tSpecify <dstDriveName>\n"\
"\t-n\tSpecify <BatchSizeInSector> (<= 100)\n"\
"\t/write\tTo confirm copy, otherwise, just for simulation.\n"
"\t-?/h\tShow this help message\n Shareware for free distribution and evaluation.\n Composed by Kuang Yujun, Bupt (KuangYujun@263.net), and Modified by TongXiaopeng.\n ";
char Message[256];
if(argc==1){
fprintf(stdout, "%s\nError: No Options given. Press ENTER to exit for another try...", HelpMessage);
fflush(stdin);getchar();fflush(stdin);
exit(-1);
}
if(fileName== NULL) fp = stdout;
else if((fp=fopen(fileName, "wt")) == NULL) fp = stdout;
for((int)ii=1; (int)ii<argc; ((int)ii)++){
if(strnicmp(argv[ii], "-l", 2) == 0) fileName = argv[ii]+2;
else if(strnicmp(argv[ii], "-s", 2) == 0) srcDriveName = argv[ii]+2;
else if(strnicmp(argv[ii], "-d", 2) == 0) dstDriveName = argv[ii]+2;
else if(strnicmp(argv[ii], "-n", 2) == 0) blockSize = argv[ii]+2;
else if(strnicmp(argv[ii], "/write", 6) == 0) WRITE=0x03;
else if(strnicmp(argv[ii], "-h", 2) == 0
||strnicmp(argv[ii], "-?", 2) == 0
||strnicmp(argv[ii], "/?", 2) == 0
||strnicmp(argv[ii], "/h", 2) == 0){
fprintf(stdout, HelpMessage);
exit(0);
}
}
srcHardDrive=GetHardDriveIndex(srcDriveName);
dstHardDrive=GetHardDriveIndex(dstDriveName);
if(srcHardDrive == dstHardDrive){
fprintf(fp, "Cannot copy disk to itself!\n");
exit(-1);
}
if(ReadDiskPara(srcHardDrive, &type_s, &maxCylinder_s, &maxSector_s, &maxHead_s, &drivers)< 0)
{
fprintf(stdout, "sourceDisk[%s] does not exist or Disk access failure.\nPlease retry.\n", strupr(srcDriveName));
exit(-1);
}
else{
sprintf(Message, ";Disk Information Summary of SrcDrive[%s]:\n;Totoal sectors:%20lu\n;Headers:%20u\n; Cylinders:%20u\n; Sectors:%20u\n",
srcDriveName, maxSectors, maxHead_s, maxCylinder_s, maxSector_s);
fprintf(stdout, Message);
if(fp != stdout)fprintf(fp, Message);
}
if(ReadDiskPara(dstHardDrive, &type_d, &maxCylinder_d, &maxSector_d, &maxHead_d, &drivers)< 0)
{
fprintf(stdout, "destDisk[%s] does not exist or Disk access failure.\nPlease retry.\n", strupr(dstDriveName));
exit(-1);
}
else{
sprintf(Message, ";Disk Information Summary of DstDrive[%s]:\n;Totoal sectors:%20lu\n;Headers:%20u\n; Cylinders:%20u\n; Sectors:%20u\n",
dstDriveName, maxSectors, maxHead_d, maxCylinder_d, maxSector_d);
fprintf(stdout, Message);
if(fp != stdout)fprintf(fp, Message);
}
if(type_s == type_d &&
maxCylinder_s == maxCylinder_d &&
maxSector_s == maxSector_d &&
maxHead_s == maxHead_d)
{
char ScreenBuffer[25*80*4];
int x,y;
gettext(1,1,80,25, ScreenBuffer);
x = wherex(); y = wherey();
clrscr();
gotoxy(10,10);
cprintf("Ready to copy disk[%c] to disk[%c]. Confirm to continue(Y/N)?", srcDriveName[0], dstDriveName[0]);
if(getche()!='Y'){
puttext(1,1,80,25,ScreenBuffer);
gotoxy(x,y);
exit(-1);
}
if(blockSize == NULL)
{
maxBlock = MAX_SECTOR_NUMBER;
}
else
{
int tmp;
if(!sscanf(blockSize, "%d", &tmp)) maxBlock=1;
else
{
if(tmp > MAX_SECTOR_NUMBER) maxBlock = MAX_SECTOR_NUMBER;
else maxBlock = tmp;
}
}
maxSectors = (DWORD)maxCylinder_s*maxSector_s*(maxHead_s+1);
Head = 0;
Cylinder = 0;
Sector = 1;
for(ii = 0; ii < maxSectors;)
{
int jj;
gotoxy(1,1);
cprintf(";Reading[%c]:(%c)%9lu/%-9lu[Head:%4u/ Cylinder:%5u/ Sector:%2u] by %3d", \
srcDriveName[0], ProgressMark(), ii, maxSectors, Head, Cylinder, Sector, maxBlock);
jj=ReadSector((char*)MBRs, maxBlock, Cylinder, Head, Sector,srcHardDrive);
if(jj >= 0)
{
gotoxy(1,2);
cprintf(";Writing[%c]:(%c)%9lu/%-9lu[Head:%4u/ Cylinder:%5u/ Sector:%2u] by %3d", \
dstDriveName[0], ProgressMark(), ii, maxSectors, Head, Cylinder, Sector, maxBlock);
jj=WriteSector((char*)MBRs, maxBlock, Cylinder, Head, Sector,dstHardDrive);
if(jj < 0){
fprintf(stdout, "\n\n\n\n;Disk Access Failure:[Code %02X]------Sectors Skipped.\n", -jj);
}
}
else{
fprintf(stdout, "\n\n\n\n;Disk Access Failure:[Code %02X]------Sectors Skipped.\n", -jj);
}
if(kbhit()){
int key;
if((key = getch()) == 0){
key = getch();
}
else{
if(key == 0x1B){
puttext(1,1,80,25,ScreenBuffer);
gotoxy(x,y);
exit(-1);
}
}
}
ii += maxBlock;
Sector = ii%maxSector_s+1;
Head = (ii/maxSector_s)%(maxHead_s+1);
Cylinder = (ii/maxSector_s/(maxHead_s+1))%maxCylinder_s;
}
if(fp != stdout) fclose(fp);
puttext(1,1,80,25,ScreenBuffer);
gotoxy(x,y);
}
else{
fprintf(fp, "Disk Parametert not compatible. Abort operation.\n");
exit(-1);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -