⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 clone.c

📁 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, &REGs);
	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, &REGs_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, &REGs);
	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 + -